【问题标题】:Beginner Dynamic SQL Building初学者动态 SQL 构建
【发布时间】:2017-12-15 18:04:43
【问题描述】:

我想开始探索使用动态 sql。我知道这个用例并不是展示使用动态 SQL 的好处的最佳示例,但我只是想了解一下语法。

在下面的查询中,我要做的就是使用 newid 创建一个表,这样我就可以获得一个不同的表名,然后简单地选择一些数据到该表中,这样我就可以在它上面运行一些选择语句。到目前为止,这是我想出的:

        SET NOCOUNT ON;

        DECLARE @TableName NVARCHAR(40); 
        DECLARE @sql NVARCHAR(MAX);
        DECLARE @guardvar NVARCHAR(1);

        SET @TableName = 'tmp_' + CONVERT(CHAR(36) , NEWID());
        SET @guardvar = 'y';



        SET @sql = 'SELECT  X.CLIENT_GUARANTOR_ID
,X.NAME
,X.RELATIONSHIP
,X.PHONE_AREA_CODE
,X.PHONE_NUMBER
,X.RECEIVE_STATEMENTS
,X.CONTACT_APPOINTMENTS
,X.sourceclient_id
into workdb.dbo.' + @TableName
            + ' 
FROM    ( SELECT    g.CLIENT_GUARANTOR_ID
,g.PERSON_ID AS sourceclient_id
,g.NAME
,g.PHONE_AREA_CODE
,g.PHONE_NUMBER
,g.RECEIVE_STATEMENTS
,g.CONTACT_APPOINTMENTS
,g.RELATIONSHIP
,ROW_NUMBER() OVER ( PARTITION BY s.SourceClient_ID ORDER BY g.CLIENT_GUARANTOR_ID DESC ) AS rnum
FROM      MDB131.CenternetDB.dbo.CEN_CEN_CLIENT_GUARANTOR
AS g
INNER JOIN ndw3nfdb.dbo.QV_PROD_Service AS s
WITH ( NOLOCK ) ON CAST(s.SourceClient_ID AS VARCHAR(50)) = CAST(g.PERSON_ID AS VARCHAR(50))
INNER JOIN ndw3nfdb.dbo.ClientProgram cp
WITH ( NOLOCK ) ON cp.Client_ID = s.Client_ID
WHERE     LEGAL_GUARDIAN = ' + @guardvar + ' 
AND g.NAME IS NOT NULL
AND cp.PROG_ID = 683
) X
WHERE   X.rnum = 1';

        EXEC sp_executesql @sql , @guardvar;

我知道我在这里遗漏了一些非常明显的东西,但我似乎无法弄清楚它是什么。当我按原样执行时,我收到以下错误消息:

Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'y'.
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near '-'.
Msg 102, Level 15, State 1, Line 28
Incorrect syntax near 'X'.

如果您对此有任何帮助,我们将不胜感激,如果您对动态 sql 有一些一般性建议,我很想听听他们的意见。谢谢。

【问题讨论】:

  • 你需要学会调试。注释掉EXEC,加PRINT @sql。看看你得到了什么。
  • 不是完全没问题。 y 的值需要在引号 'y' 之间
  • 看看下面的答案。你需要额外的报价'
  • LEGAL_GUARGIAN = ''' + @guardvar + ''' AND ...
  • @Eric 做到了。我搞砸了我的串联。有没有其他方法可以在不使用引号的情况下获得'y'

标签: sql-server tsql dynamic-sql


【解决方案1】:

这是不对的。

WHERE LEGAL_GUARDIAN = ' + @guardvar + '

您正在使用带有EXEC sp_executesql @sql , @guardvar; 的参数化查询,因此只需像往常一样编写您的sql 语句。

WHERE LEGAL_GUARDIAN = @guardvar

或者,您可以在值周围连接单引号,例如WHERE LEGAL_GUARDIAN = ' + ''' + @guardvar + ''' + '。我不推荐这种方法。

为了澄清当您打印您的 sql 语句时,您希望看到以下任一内容

作品

  • WHERE LEGAL_GUARDIAN = @guardvar --Works with parameterized Sql proc sp_executesql
  • WHERE LEGAL_GUARDIAN = 'y' --Standard dynamic sql. Potential SQL injection

如果你打印你的 sql 并且它看起来像这样它不会工作。

不起作用

  • WHERE LEGAL_GUARDIAN = '@guardvar' --Filters for a string @guardvar which returns 0 records
  • WHERE LEGAL_GUARDIAN = y --Won't compile

两个音符

  1. 在调试动态sql时,你应该有Print @sql语句,这样你就可以静态编译语句来发现这样的错误。

  2. 看起来您正在创建临时表。您可能应该使用 #table##table 临时表,并且不要为非临时表、临时表和动态 sql 烦恼,即使您提到您正在尝试理解语法

【讨论】:

  • 所以,我设法清理了表名。当我运行Print @sql 时,我没有得到into workdb.dbo.[tmp_1E6F86CB-8C4F-4AD7-8D02-AD2333452C16],这很好。不过,我似乎无法让我的@guardvar 工作。这是我目前拥有的东西,以及我从印刷品中得到的东西。 WHERE LEGAL_GUARDIAN = '+'''@guardvar'''+ ' AND g.NAME IS NOT NULL打印返回:WHERE LEGAL_GUARDIAN = '@guardvar'
  • @AngusGray 我试图澄清我的答案。您在三引号和变量名称之间缺少+。那就是说你根本不需要那个。只需将您的动态sql更改为WHERE LEGAL_GUARDIAN = @guardvar
猜你喜欢
  • 2018-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多