2011-02-01 33 views
0

好吧,我不是SQL大師或DBA,所以如果有更好的方法可以做到這一點,那麼請自由發言。如何使用開始和結束語句構建動態TSQL查詢

但是我需要特別做的是增強現有的使用dyanmic SQL不存在重複值的存儲過程。 SQL在單獨表格中獨立時是件小事。不過現在,我遇到了一個通用存儲過程的問題,我有一些通用的表,並使用TSQL。問題在於BEGIN和END語句。

SET @Query = 'IF NOT EXISTS (SELECT ' + @DescriptionFieldName + ' 
     FROM '+ @TableName +' 
     WHERE (' + @DescriptionFieldName + ' = ''' + @DescriptionValue + ''') 

    BEGIN 
     INSERT INTO '+ @TableName +' (' + @DescriptionFieldName + ', LastUser, LastUpdate) VALUES ('''+ ISNULL(@DescriptionValue, '') +''', '''+ ISNULL(@LastUser, '') +''',Convert(Varchar, GetDate())) ' + 'SELECT CAST(scope_identity() AS int); 
    END' 

EXEC (@Query) 

當我EXEC更改爲PRINT,一切似乎是OK的語法明智的,但它使用EXEC時提供了以下錯誤:

「關鍵字附近有語法錯誤‘BEGIN’ 「。

有沒有人有關於如何解決此問題的想法,以便查詢將工作?

謝謝!

回答

2

看起來你在where子句後面有一個缺失的圓括號。

SET @Query = 'IF NOT EXISTS (SELECT ' + @DescriptionFieldName + ' 
     FROM '+ @TableName +' 
     WHERE (' + @DescriptionFieldName + ' = ' + @DescriptionValue + ')) 

    BEGIN 
     INSERT INTO '+ @TableName +' (' + @DescriptionFieldName + ', LastUser, LastUpdate) VALUES ('''+ ISNULL(@DescriptionValue, '') +''', '''+ ISNULL(@LastUser, '') +''',Convert(Varchar, GetDate())) ' + 'SELECT CAST(scope_identity() AS int); 
    END' 
+0

是的好抓 - 畢竟與BEGIN和END無關。我還必須在@DescriptionValue周圍添加(3)tic標記(爲將來的讀者修改原始帖子),因爲它是這樣的varchar:WHERE('+ @DescriptionFieldName +'='''+ @DescriptionValue +'''))。 (3)tic方法是否是最好的方法? – atconway 2011-02-01 16:19:01

1

FWIW時,與即時動態SQL進行生產或在代碼生成我喜歡用模板,這使得它更容易一些,以保持打交道時(請注意,你可以嵌入換行,這也是尼斯 - 沒有忘記插入CHAR(13)/ CHAR(10)或者需要一個空間報價前):

DECLARE @template AS varchar(max) = ' 
    IF NOT EXISTS (
     SELECT {@DescriptionFieldName} -- Note this is unnecessary 
     FROM {@TableName} 
     WHERE ({@DescriptionFieldName} = ''{@DescriptionValue}'' 
    ) 
    BEGIN 
     INSERT INTO {@TableName} ({@DescriptionFieldName}, LastUser, LastUpdate) 
     VALUES (''{@DescriptionValue}'', ''{@LastUser}'', ''{@LastUpdate}''); 
    END 
' 

DECLARE @Query AS varchar(max) = @template 
SET @Query = REPLACE(@Query, '{@DescriptionFieldName}', @DescriptionFieldName) 
SET @Query = REPLACE(@Query, '{@TableName}', @TableName) 
SET @Query = REPLACE(@Query, '{@DescriptionValue}', ISNULL(@DescriptionValue, '')) 
SET @Query = REPLACE(@Query, '{@LastUser}', ISNULL(@LastUser, '')) 
SET @Query = REPLACE(@Query, '{@LastUpdate}', @LastUpdate) 

PRINT @Query 
EXEC (@Query) 

您仍然增加了一倍的報價,但你並不需要添加串起來,當你忘記替換一個參數時,很明顯,當事情不得不改變時,你不會在代碼中重複插入。

還要注意的是,這可能有問題,在@DescriptionValue NULL(你原來曾在WHERE部分同樣的問題在EXISTS)

請注意,您還可以嵌套的替換並以適當的格式,它可以甚至是可讀的:

DECLARE @Query AS varchar(max) = @template 
SET @Query = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@Query 
       ,'{@DescriptionFieldName}', @DescriptionFieldName) 
       ,'{@TableName}', @TableName) 
       ,'{@DescriptionValue}', ISNULL(@DescriptionValue, '')) 
       ,'{@LastUser}', ISNULL(@LastUser, '')) 
       ,'{@LastUpdate}', @LastUpdate) 
+0

非常好我喜歡這種方法作爲'改進'我原來的TSQL。感謝您發表並展示這一點。 – atconway 2011-02-01 16:59:39