验证查询中的所有位置是否都进行了特定的联接

2024-01-03

我必须以存储过程的形式执行数百个查询,并验证每个连接是否满足以下条件:

  1. 始终在连接中进行特定的列连接
  2. 连接不以硬编码格式存在于该列的前一个唯一值(即它需要类似于 a.requiredJoinColumn = b.requiredJoinColumn 而不是 a.requiredJoinColumn = 'onlyValue'

例如,如果所需的列名为“reqCol”,我想将此视为一个问题:

SELECT a.* 
FROM tableA a
JOIN table b ON a.OtherColumn = b.OtherColumn

also,

SELECT a.* 
FROM tableA a
JOIN table b ON a.reqCol = b.reqCol
JOIN table c ON a.OtherColumn = c.otherColumn

另外,我希望这不会成为一个问题

SELECT a.* 
FROM tableA a
JOIN table b ON a.reqCol = b.correctColButDifferentName

我还需要它能够处理明确声明的内部和外部联接,以及通过逗号完成联接的情况(即 select * from tableA, tableB where a.OtherColumn = b.OtherColumn)

现在我正在手动处理这个问题,这需要很长时间,所以我希望可能有一个我可以使用的工具。也许我可以将一些验证逻辑写入或与 SQL Server 数据库中的一系列存储过程一起执行。


您可以“导出”sql_modules 并将它们提供给 sql 解析器,或者您可以在 sql server 中引入解析器并在内部处理它们(有点非正统,但同时“有创意”)。

有一个.Net 中的 smo 解析器 https://learn.microsoft.com/en-us/dotnet/api/microsoft.sqlserver.management.sqlparser.parser.parser它可以在 clr 模块中使用(例如标量函数)

//r: Microsoft.SqlServer.Management.SqlParser.dll
using System;
using Microsoft.SqlServer.Server;
using Microsoft.SqlServer.Management.SqlParser.Parser;
using System.Reflection;


namespace sqlns
{
    public partial class SQLParser
    {
        [SqlFunction(DataAccess = DataAccessKind.None)]
        [return: SqlFacet(MaxSize = -1)]
        public static string SQLParseToXml(string sqlquery)
        {
            if (string.IsNullOrEmpty(sqlquery))
            {
                return sqlquery;
            }

            ParseResult pres = Parser.Parse(sqlquery);
            Object script = pres.GetType().GetProperty("Script", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(pres, null);
            String xmlstr = script.GetType().BaseType.GetProperty("Xml").GetValue(script, null).ToString();
            return xmlstr;
        }
    }
}

构建 dll 并将以下两个 dll 复制到构建位置:

Microsoft.SqlServer.Management.SqlParser.dll

Microsoft.SqlServer.Diagnostics.STrace.dll

创建程序集和 clr 函数:

create assembly sqlparse from 'C:\path to the project\bin\Debug\xyz.dll'
with permission_set = unsafe;
go

create function dbo.parseSqlToXml(@sql nvarchar(max))
returns nvarchar(max)
with execute as caller, returns null on null input
as
external name [sqlparse].[sqlns.SQLParser].SQLParseToXml;

您必须仔细检查解析器的 xml 结构并找到一种方法来获取您需要的内容。

对于启动(和灵感):

select src.modulename,  
    t.col.value('../comment()[1]', 'nvarchar(500)') as joincondition,
    replace(left(t.col.value('(..//*/@Location)[1]', 'varchar(20)'), charindex(',', t.col.value('(..//*/@Location)[1]', 'varchar(20)'))), '(', '') as linenumber, 
    t.col.value('./comment()[1]', 'nvarchar(500)') as columncondition,
    t.col.value('(./SqlScalarRefExpression[1]/@ColumnOrPropertyName)[1]', 'nvarchar(200)') as leftcol,
    t.col.value('(./SqlScalarRefExpression[2]/@ColumnOrPropertyName)[1]', 'nvarchar(200)') as rightcol,
    t.col.value('(./SqlLiteralExpression[1]/@Value)[1]', 'nvarchar(200)') as literal
from 
(
    select object_name(object_id) as modulename, cast(dbo.parseSqlToXml(definition) as xml) as definitionxml
    from sys.sql_modules
) as src
cross apply src.definitionxml.nodes('//SqlQualifiedJoinTableExpression/SqlConditionClause//SqlComparisonBooleanExpression') as t(col);

以上,将产生类似于以下的结果集(摘录于 msdb 中的模块)

| modulename                                     | joincondition                                                             | linenumber | columncondition                                 | leftcol              | rightcol      | literal                              |
|------------------------------------------------|---------------------------------------------------------------------------|------------|-------------------------------------------------|----------------------|---------------|--------------------------------------|
| syscollector_execution_log_full                | (p.id = t.package_id AND p.id != N'84CEC861-D619-433D-86FB-0BB851AF454A') | 25,        | p.id != N'84CEC861-D619-433D-86FB-0BB851AF454A' | id                   | NULL          | 84CEC861-D619-433D-86FB-0BB851AF454A |
| sp_syscollector_delete_execution_log_tree      | ON (node.log_id = leaf.parent_log_id)                                     | 25,        | (node.log_id = leaf.parent_log_id)              | log_id               | parent_log_id | NULL                                 |
| sp_syscollector_delete_execution_log_tree      | ON (l.package_execution_id = s.executionid)                               | 34,        | (l.package_execution_id = s.executionid)        | package_execution_id | executionid   | NULL                                 |
| sp_syscollector_delete_execution_log_tree      | ON i.log_id = l.log_id                                                    | 35,        | i.log_id = l.log_id                             | log_id               | log_id        | NULL                                 |
| sp_syscollector_delete_execution_log_tree      | ON i.log_id = l.log_id                                                    | 40,        | i.log_id = l.log_id                             | log_id               | log_id        | NULL                                 |
| sp_syscollector_delete_collection_set_internal | ON (cs.schedule_uid = sv.schedule_uid)                                    | 29,        | (cs.schedule_uid = sv.schedule_uid)             | schedule_uid         | schedule_uid  | NULL                                 |
| sysutility_mi_configuration                    | ON 1=1                                                                    | 11,        | 1=1                                             | NULL                 | NULL          | 1                                    |
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

验证查询中的所有位置是否都进行了特定的联接 的相关文章

  • sql server GO 相当于 oracle

    我正在为 Oracle 编写迁移脚本 我需要更改表结构 然后用数据填充它 我想先进行结构更改 然后再进行数据更改 在 SQL Server 中我会使用GO分离批次 是否有 SQL ServerGOOracle 中的等效命令 It s and
  • SSRS。如何在table1_Details_Group右侧创建新的行组?

    我正在使用 Microsoft Visual Studio 2013 创建报告 PROBLEM 如果我添加新的Row Group前面会自动添加table1 Details Group 问题 如何更改组的顺序或在右侧添加新组table1 De
  • SQL Server 转换选择一列并将其转换为字符串

    是否可以编写一条从表中选择列并将结果转换为字符串的语句 理想情况下 我希望有逗号分隔的值 例如 假设 SELECT 语句看起来像这样 SELECT column FROM table WHERE column lt 10 结果是一列包含值的
  • 如何找出我的 MS SQL Server 排序规则是什么?

    是否有我可以执行的 SQL 来找出答案 服务器默认排序规则 select serverproperty collation 哪个是相同的 select databasepropertyex master collation Check 服务
  • PHP DBlib PDO 问题

    我正在尝试通过 php 连接到 MSSQL 服务器 但我的 pdo 连接给我带来了困难和我不太理解的错误 我在下面粘贴的代码一周前运行得很好 突然间它就停止了 没有任何人进行任何更改 我仍然可以连接到服务器并直接从命令行运行查询 但我在 p
  • 与 FOREIGN KEY 约束冲突

    我有两张桌子 学术界 CREATE TABLE dbo R ACADEMIE ID ACADEMIE dbo IDENTIFIANT NOT NULL LC ACADEMIE CODE dbo LIBELLE COURT NOT NULL
  • 如何在测试期间强制锁定升级(以消除死锁问题)?

    在此发布问题和一个答案 也许有人有更好的答案 编写触发死锁的代码是可能的即使对于单个用户如果开发人员不小心打开了与数据库的第二个连接 而不是重用现有的连接 可能已经有一个打开的事务 某些 O RM 和 LINQ 框架很容易犯这个错误 以下是
  • 仅基于月份和年份的 SQL Server 日期比较

    我无法确定仅根据月份和年份比较 SQL 中的日期的最佳方法 我们根据日期进行计算 由于计费是按月进行的 因此该月的日期会造成更多障碍 例如 DECLARE date1 DATETIME CAST 6 15 2014 AS DATETIME
  • 在 Dockerfile 中切换到 root 用户

    我运行了这个命令 docker pull mcr microsoft com mssql server 2019 latest 然后我创建了一个 dockerfile 来使用此容器映像作为另一个容器的基础映像 escape FROM mcr
  • 数据库设计1对1关系

    我的数据库设计不正确 我应该在开发过程中解决这个问题吗 假定 user 表与 userprofile 表具有 1 1 关系 然而 实际设计中 用户 表与 用户配置文件 表具有 1 关系 一切正常 但无论如何应该修复它吗 做一件事 User
  • 如何删除实体框架6中的多对多关系

    如果将项目连接为多对多关系 则从数据库中删除项目时会出现问题 我的数据库看起来像 Project lt JobInProject gt Job ProjectID JobInProjectID JobID ProjectID JobID 主
  • 临时表上没有外键限制? SQL Server 2008

    我知道临时表只会在 SQL Server 会话打开时存在 但为什么不能对它们进行外键限制呢 想象一下这样的场景 您创建从临时表到具体表的键的外键关系 外键关系的限制之一是您无法从临时表所依赖的键表中删除行 现在 通常当您创建外键关系时 您知
  • 如何获取 dm_exec_sql_text 的参数值

    我正在运行以下语句来查看 sql server 中正在执行哪些查询 select from sys dm exec requests r cross apply sys dm exec sql text r sql handle where
  • SQL Server 全文的自定义断字器

    有谁知道如何为 SQL Server 2005 创建自定义分词系统 我更喜欢用 C 编写它 我需要能够搜索 c f 等术语 但 字符是英语 英国 分词器组件中的分词器 不能以任何其他方式更改 我发现以下文章提供了不完整的示例 缺少 IWor
  • NOLOCK 和 UNCOMMITTED 之间有什么区别

    我使用 SQL Server 2012 我写了两个查询 但是它们之间有什么不同NOLOCK and UnCommitted SELECT lastname firstname FROM HR Employees with READUNCOM
  • 自定义 Sql Server 对象资源管理器右键单击菜单项

    如何在 Sql Server 2012 的对象资源管理器中添加或自定义右键菜单项 例如 我想将新项目添加到表右键菜单中以生成自定义表创建器脚本 您可以编写一个 SSMS 加载项 See http sqlblogcasts com blogs
  • SQL Server - 即使在回滚的情况下如何确保标识字段正确增加

    在 SQL Server 中 如果涉及插入新行的事务被回滚 则标识字段中的数字将被跳过 例如 如果Foos表是99 然后我们尝试插入一个新的Foo记录但回滚 然后 ID 100 被 用完 下一个Foo行编号为 101 有什么方法可以改变这种
  • 如何在 BigQuery/SQL 中将行转置为包含大量数据的列?

    我在将 BigQuery 中的大量数据表 15 亿行 从行转置为列时遇到问题 我可以弄清楚如何在硬编码时使用少量数据来完成此操作 但是对于如此大量的数据 该表的快照如下所示 CustomerID Feature Value 1 A123 3
  • 使用 FTS 进行搜索相对于在索引列上使用 LIKE 进行搜索的性能有何提升)?

    质疑 全文搜索sql server 2005 https stackoverflow com questions 3627583 full text search sql server 2005 3824263 3824263 与在索引列上
  • 将语句插入 SQL Server 数据库

    最近几天我试图找到这个错误 但没有成功 我正在尝试在数据库中插入一个新行 一切都很顺利 没有错误 也没有程序崩溃 My INSERT声明如下 INSERT INTO Polozaj Znesek Uporabnik Cas Kupec Po

随机推荐