【问题标题】:sp_execute SQL giving different results to raw querysp_execute SQL 为原始查询提供不同的结果
【发布时间】:2017-10-05 13:13:39
【问题描述】:

我发现了一些与此类似的问题,但所有解决方案似乎都与将日期参数传递给 sp_executesql 相关,这不是我正在做的......

我有一个 .NET 应用程序,它使用 SqlConnection 和 SqlCommand 类连接到 SQL 数据库。当我使用 SQL Server Profiler 运行应用程序并监视数据库查询时,我可以看到 .NET 应用程序正在生成以下代码:

exec sp_executesql N'IF object_id(''tempdb..#ParmsInProc'') IS NOT NULL DROP TABLE #ParmsInProc 
                     SELECT o.name AS ProcName, o.object_id, p.name AS ParamName, p.system_type_id, p.user_type_id
                     INTO   #ParmsInProc
                     FROM   sys.objects o
                            JOIN sys.parameters p
                                ON o.object_id = p.object_id
                            JOIN sys.types t
                                ON t.system_type_id = p.system_type_id AND t.user_type_id = p.user_type_id
                    WHERE   type_desc = ''SQL_STORED_PROCEDURE'' AND o.name = ''@sp''

                    SELECT  * 
                    FROM    #ParmsInProc p        
                            LEFT JOIN ( 
                                            SELECT  * 
                                            FROM    #ParmsInProc 
                                            WHERE   system_type_id = 56 AND user_type_id = 56 
                                        ) ints 
                                ON p.system_type_id = ints.system_type_id AND p.user_type_id = ints.user_type_id',N'@sp nvarchar(14)',@sp=N'sp_myProcedure'

如果我在 SSMS 中运行该代码,我不会得到任何结果。但是,如果我复制查询并将参数占位符替换为实际值,我会得到 ​​p>

IF  object_id('tempdb..#ParmsInProc') IS NOT NULL DROP TABLE #ParmsInProc 
SELECT  o.name AS ProcName, o.object_id, p.name AS ParamName, p.system_type_id, p.user_type_id
INTO    #ParmsInProc
FROM    sys.objects o
        JOIN sys.parameters p
            ON o.object_id = p.object_id
        JOIN sys.types t
            ON t.system_type_id = p.system_type_id AND t.user_type_id = p.user_type_id
WHERE   type_desc = 'SQL_STORED_PROCEDURE' AND o.name = 'sp_myProcedure'

SELECT  * 
FROM    #ParmsInProc p        
        LEFT JOIN ( 
                        SELECT  * 
                        FROM    #ParmsInProc 
                        WHERE   system_type_id = 56 AND user_type_id = 56 
                    ) ints 
            ON p.system_type_id = ints.system_type_id AND p.user_type_id = ints.user_type_id

如果我运行它,我会得到一个结果(这是我期望的结果)

这可能是什么原因造成的?

【问题讨论】:

  • Declare @spSet @sp 初始阶段和尝试。
  • 我不认为这是问题,但参数是 NVARCHARS 而你的字符串是 VARCHAR

标签: sql-server sql-server-2008-r2 ado.net


【解决方案1】:

如果您尝试“调试”您的初始查询,您将看到 @sp 作为过程名称而不是参数的实际值被传递。

您可以通过编写以下内容来看到这一点:

declare @spname nvarchar(100) = 'my_storedproc';
declare @sql nvarchar(max) = '   IF object_id(''tempdb..#ParmsInProc'') IS NOT NULL DROP TABLE #ParmsInProc 
                                 SELECT o.name AS ProcName, o.object_id, p.name AS ParamName, p.system_type_id, p.user_type_id
                                 INTO   #ParmsInProc
                                 FROM   sys.objects o
                                        JOIN sys.parameters p
                                            ON o.object_id = p.object_id
                                        JOIN sys.types t
                                            ON t.system_type_id = p.system_type_id AND t.user_type_id = p.user_type_id
                                WHERE   type_desc = ''SQL_STORED_PROCEDURE'' AND o.name = ''@sp'';

                                SELECT  * 
                                FROM    #ParmsInProc p        
                                        LEFT JOIN ( 
                                                        SELECT  * 
                                                        FROM    #ParmsInProc 
                                                        WHERE   system_type_id = 56 AND user_type_id = 56 
                                                    ) ints 
                                            ON p.system_type_id = ints.system_type_id AND p.user_type_id = ints.user_type_id;'
print @sql

正在生成以下内容:

你需要做的只是将它作为参数传递,不需要引号。 我修改了一点你的查询只是为了能够打印它,通过将 sql 查询存储到一个变量中,但你当然可以按照你的方式执行它,内联:

declare @spname nvarchar(100) = 'my_storedproc';
declare @sql nvarchar(max) = '   IF object_id(''tempdb..#ParmsInProc'') IS NOT NULL DROP TABLE #ParmsInProc 
                                 SELECT o.name AS ProcName, o.object_id, p.name AS ParamName, p.system_type_id, p.user_type_id
                                 INTO   #ParmsInProc
                                 FROM   sys.objects o
                                        JOIN sys.parameters p
                                            ON o.object_id = p.object_id
                                        JOIN sys.types t
                                            ON t.system_type_id = p.system_type_id AND t.user_type_id = p.user_type_id
                                WHERE   type_desc = ''SQL_STORED_PROCEDURE'' AND o.name = @sp;

                                SELECT  * 
                                FROM    #ParmsInProc p        
                                        LEFT JOIN ( 
                                                        SELECT  * 
                                                        FROM    #ParmsInProc 
                                                        WHERE   system_type_id = 56 AND user_type_id = 56 
                                                    ) ints 
                                            ON p.system_type_id = ints.system_type_id AND p.user_type_id = ints.user_type_id;'
print @sql
exec sp_executesql @sql, N'@sp nvarchar(100)', @sp = @spname

这将成功执行,您可以在 Messages 选项卡下看到打印的 sql 查询:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-11
    • 2020-08-20
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 1970-01-01
    相关资源
    最近更新 更多