好吧我不是SQL大师或DBA,所以如果有更好的方法可以做到这一点,那么请自由发言。
但是我需要特别做的是增强使用动态SQL的现有存储过程不插入重复值。当对单个表进行specefic时,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时,所有出现都是正确的语法,但在使用EXEC时出现以下错误:
“关键字'BEGIN'附近的语法不正确。”
有没有人知道如何纠正这个问题,以便查询有效?
谢谢!
答案 0 :(得分: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'
答案 1 :(得分: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可能存在问题(您的原始文件在EXISTS的WHERE部分中存在同样的问题)
请注意,您也可以嵌套替换,并使用适当的格式,它甚至可以读取:
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)