sp_execute SQL为原始查询提供不同的结果

时间:2017-10-05 13:13:40

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

我发现了一些类似的问题但是所有解决方案似乎都与将日期参数传递给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中运行该代码,则无法获得任何结果。但是,如果我复制出查询并用实际值替换参数占位符,我会得到

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

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

导致这种情况的原因是什么?

1 个答案:

答案 0 :(得分: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

正在生成以下内容:

enter image description here

您需要做的是将其作为参数传递,不需要引号。 我修改了一些你的查询只是为了能够打印它,通过将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查询:)