我需要帮助处理存储过程中的一段代码,该代码将数据集返回到包含一组变量列的.NET应用程序 - 标准列和用户定义的列。我的代码创建一个临时表来保存数据集并附加自定义列。我遇到的问题是这些自定义列的数量。 (顺便说一句,我的代码需要与Microsoft SQL Server 2008 R2兼容)。
我想使用动态SQL将Update语句组合在一起,该语句使用存储在查找表中的SQL片段更新临时表中自定义列的值。
例如,用户可能希望自定义字段包含以某种方式连接的员工姓名(例如"姓氏,名字和#34;),因此自定义字段的SQL片段将是"姓氏+',' + FirstName"连接临时表中的FistName和LastName字段。这很容易。困难的部分是当需要使用传递给sproc的变量填充自定义字段时,比如创建一个唯一的ID(例如,自定义字段的SQL片段是' Inc _' + CAST(MONTH(@)如果输入参数@PayrollDate是' 10/15/17'),PayrollDate)AS VARCHAR)'得到' Inc_10'。
还在我身边吗?好的,让我们做一些SQL。
假设我们有一个带有标准字段的临时表,然后添加几个自定义字段,如下所示(请不要注意我的alter table方法;在我真正的sproc中,我使用动态SQL根据查找表中保存的值附加字段。
-- 1. Create the temp table with the standard fields
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
DROP TABLE #MyTempTable
CREATE TABLE #MyTempTable (
EmpID VARCHAR(50),
FirstName VARCHAR(100),
LastName VARCHAR(100),
EarningsValue MONEY)
-- 2. Add sample earnings data to the temp table
INSERT INTO #MyTempTable (EmpID,FirstName,LastName,EarningsValue) VALUES('1234','Tom','Jones',525.50)
INSERT INTO #MyTempTable (EmpID,FirstName,LastName,EarningsValue) VALUES('4455','Mary','Smith',800.25)
INSERT INTO #MyTempTable (EmpID,FirstName,LastName,EarningsValue) VALUES('9876','Aaron','Lee',200.00)
-- 3. Add the custom fields to the temp table
ALTER TABLE #MyTempTable ADD EmployeeName VARCHAR(100)
ALTER TABLE #MyTempTable ADD BatchID VARCHAR(50)
我知道有两种方法可以执行动态SQL来填充我的自定义字段。中途工作的方法是EXEC(@SQL)方法,你可以这样做:
DECLARE @SQL VARCHAR(1000), @CustomField VARCHAR(50), @SQLSnippet VARCHAR(500)
SELECT @CustomField = 'EmployeeName', @SQLSnippet = 'LastName + '','' + FirstName'
SET @SQL = 'UPDATE #MyTempTable SET ' + @CustomField + ' = ' + @SQLSnippet
EXEC(@SQL)
如果你要做PRINT @SQL而不是EXEC(@SQL),你会得到:
UPDATE #MyTempTable SET EmployeeName = LastName + ',' + FirstName
如果我选择SELECT * FROM #MyTempTable,我会看到我的'员工姓名'自定义字段填充得很好。
要使用的另一个动态SQL方法是sp_executesql。但是,如果我尝试进行更新,我会得到NOTHING,因为它在我的SET语句中没有识别@CustomField。
DECLARE @NSQL NVARCHAR(1000), @CustomField NVARCHAR(50), @SQLSnippet NVARCHAR(500)
SELECT @CustomField = 'EmployeeName', @SQLSnippet = 'LastName + '','' + FirstName'
SET @NSQL = 'UPDATE #MyTempTable SET @CustomField = @SQLSnippet'
EXECUTE sp_executesql @NSQL,N'@CustomField NVARCHAR(50), @SQLSnippet NVARCHAR(500)',@CustomField,@SQLSnippet
如果我执行PRINT @NSQL,我会获得UPDATE #MyTempTable SET @CustomField = @SQLSnippet。显然,这看起来不太好,但从理论上讲,传入@CustomField和@SQLSnippet字段的值应该有效,不应该吗?
此时,您正在思考,史蒂夫,为什么不使用EXEC(@SQL)方法并忘记sp_executesql废话?"啊,但是有一个问题。
如果我需要在SQL片段中使用变量来使用动态SQL,则EXEC(@SQL)方法会失败。它抱怨'必须声明标量变量" @ PayrollDate"'。真?是的,真的。试试吧......
DECLARE @SQL VARCHAR(1000), @CustomField VARCHAR(50), @SQLSnippet VARCHAR(500), @PayrollDate SMALLDATETIME
SET @PayrollDate = '10/15/17'
SELECT @CustomField = 'BatchID', @SQLSnippet = '''INC_'' + CAST(MONTH(@PayrollDate) AS VARCHAR)'
SET @SQL = 'UPDATE #MyTempTable SET ' + @CustomField + ' = ' + @SQLSnippet
EXEC(@SQL)
根据我在线研究的内容,只有sp_executesql使用动态SQL中的参数。但是,我仍然无法使用它获得任何结果。这是使用sp_executesql的动态SQL:
DECLARE @NSQL NVARCHAR(1000), @CustomField NVARCHAR(50), @SQLSnippet NVARCHAR(500), @PayrollDate SMALLDATETIME
SET @PayrollDate = '10/15/17'
SELECT @CustomField = 'BatchID', @SQLSnippet = '''INC_'' + CAST(MONTH(@PayrollDate) AS VARCHAR)'
SET @NSQL = 'UPDATE #MyTempTable SET @CustomField = @SQLSnippet'
EXECUTE sp_executesql @NSQL, N'@CustomField NVARCHAR(50),@SQLSnippet NVARCHAR(500),@PayrollDate SMALLDATETIME',@CustomField,@SQLSnippet,@PayrollDate
如果执行SELECT * FROM #MyTempTable,则BatchID自定义字段为NULL。 GRRRR!
那么如何让消隐动态SQL正常工作?我是使用EXEC(@SQL)方法还是sp_executesql方法,以及如何使用?非常感谢!
答案 0 :(得分:1)
RE:
sp_executeSQL
- 您无法将列名称作为变量传递。如果您希望列名来自变量,则需要动态构造查询字符串:
SET @NSQL = 'UPDATE #MyTempTable SET ' + @CustomField + ' = @SQLSnippet'
EXECUTE sp_executesql @NSQL, N'@PayrollDate SMALLDATETIME, @SQLSnippet NVARCHAR(500)',@PayrollDate, @SQLSnippet
原始查询的作用是将变量@SQLSnippet
中的值分配给变量@CustomField
。
答案 1 :(得分:1)
为了将数据插入到列中,首先需要将ADD
列(及其数据类型)添加到表中,因为ALTER
和UPDATE
不能相同批处理,您必须使用sp_executesql
两次。以下是将完成您想要的查询。
DECLARE @NSQL NVARCHAR(1000),@ALTSQL NVARCHAR(1000), @CustomField NVARCHAR(50), @CustomFieldDataType NVARCHAR(50), @SQLSnippet NVARCHAR(500), @PayrollDate SMALLDATETIME
SET @PayrollDate = '10/15/17'
SELECT @CustomField = 'BatchID', @CustomFieldDataType = ' NVARCHAR(50)', @SQLSnippet = '''INC_'' + CAST(MONTH(@PayrollDate) AS VARCHAR)'
SET @ALTSQL = 'ALTER TABLE #MyTempTable ADD '+ @CustomField + @CustomFieldDataType
SET @NSQL = 'UPDATE #MyTempTable SET '+ @CustomField +' = '+ @SQLSnippet
EXECUTE sp_executesql @ALTSQL, N'@CustomField NVARCHAR(50), @CustomFieldDataType NVARCHAR(50)',@CustomField, @CustomFieldDataType
EXECUTE sp_executesql @NSQL, N'@CustomField NVARCHAR(50), @SQLSnippet NVARCHAR(500),@PayrollDate SMALLDATETIME',@CustomField, @SQLSnippet,@PayrollDate
SELECT * FROM #MyTempTable
答案 2 :(得分:0)
try this
DECLARE @SQL VARCHAR(1000), @CustomField VARCHAR(50), @SQLSnippet VARCHAR(500), @PayrollDate smalldatetime
SET @PayrollDate = '10/15/17'
SELECT @CustomField = 'BatchID', @SQLSnippet = '''INC_' + CAST(MONTH(@PayrollDate) AS VARCHAR)+''''
SET @SQL = 'UPDATE #MyTempTable SET ' + @CustomField + ' = ' + @SQLSnippet
exec(@SQL)