以下是始终插入table1的原始SP(INSERT INTO table1)。现在我需要插入table1或table2,它们都具有相同的结构。
我尝试将tableName作为参数传递给SP。
ALTER PROCEDURE [dbo].[sp_importStats] (
@accountID BIGINT,
@csvFileName VARCHAR (1024),
@csvFormatFileName VARCHAR (1024)
@tableName VARCHAR(256))
然后我尝试使用EXECUTE进行INSERT,如下所示:
--Incorrect syntax near EXECUTE.
EXECUTE(
'INSERT INTO '+ @tableName + '(accountId, date, cost)
(SELECT cte.id, ms.date, ms.cost
FROM #stats ms
INNER JOIN CTE cte ON ms.accountNumber = cte.key4)');
然后我尝试了这个:
--Must declare the table variable @tableName.
INSERT INTO @tableName (accountId, date, cost)
(SELECT cte.id, ms.date, ms.cost
FROM #stats ms
INNER JOIN CTE cte ON ms.accountNumber = cte.key4);
然后我尝试不传递tableName,而是将一个布尔值传递给SP,并根据它决定我需要插入哪个表:
ALTER PROCEDURE [dbo].[sp_importStats] (
@accountID BIGINT,
@csvFileName VARCHAR (1024),
@csvFormatFileName VARCHAR (1024),
@condition BIT = 0)
IF (@condition= 0)
SET @table = 'table1'
ELSE
SET @table = 'table2'
--Must declare the table variable "@table".
INSERT INTO @table (accountId, date, cost)
(SELECT cte.id, ms.date, ms.cost
FROM #sats ms
INNER JOIN CTE cte ON ms.accountNumber = cte.key4);
无论哪种方式我都有错误。你能不能让我知道处理这件事的最佳方法是什么?为什么我收到这些错误?非常感谢任何帮助。
原始SP:
ALTER PROCEDURE [dbo].[sp_importStats] (
@accountID BIGINT,
@csvFileName VARCHAR (1024),
@csvFormatFileName VARCHAR (1024))
AS
BEGIN
CREATE TABLE #stats(
[accountID] [bigint] NOT NULL,
[accountNumber] [varchar](30) NULL,
[date] [datetime] NOT NULL,
[cost] [money] NULL,
);
EXECUTE('INSERT INTO #stats SELECT * FROM '+
'OPENROWSET (BULK N''' + @csvFileName + '''' +
',FORMATFILE='''+@csvFormatFileName+''''+
',FIRSTROW=2'+
',MAXERRORS=0'+
') AS t;');
WITH CTE(id, key4) AS (
SELECT A.id, A.[key4]
FROM VA A (NOLOCK)
WHERE A.id = @accountID
UNION ALL
SELECT A.id, A.[key4]
FROM VA A (NOLOCK)
INNER JOIN CTE ON (CTE.id = A.MAID)
WHERE A.key4 IS NOT NULL
)
INSERT INTO table1 (accountId, date, cost)
(SELECT cte.id, ms.date, ms.cost
FROM #stats ms
INNER JOIN CTE cte ON ms.accountNumber = cte.key4);
DROP TABLE #stats;
END
这就是我现在所拥有的:
ALTER PROCEDURE [dbo].[sp_importStats] (
@accountID BIGINT,
@csvFileName VARCHAR (1024),
@csvFormatFileName VARCHAR (1024)
@tableName VARCHAR(256))
AS
BEGIN
DECLARE @sql NVARCHAR(MAX);
CREATE TABLE #stats(
[accountID] [bigint] NOT NULL,
[accountNumber] [varchar](30) NULL,
[date] [datetime] NOT NULL,
[cost] [money] NULL,
);
EXECUTE('INSERT INTO #stats SELECT * FROM '+
'OPENROWSET (BULK N''' + @csvFileName + '''' +
',FORMATFILE='''+@csvFormatFileName+''''+
',FIRSTROW=2'+
',MAXERRORS=0'+
') AS t;');
WITH CTE(id, key4) AS (
SELECT A.id, A.[key4]
FROM VA A (NOLOCK)
WHERE A.id = @accountID
UNION ALL
SELECT A.id, A.[key4]
FROM VA A (NOLOCK)
INNER JOIN CTE ON (CTE.id = A.MAID)
WHERE A.key4 IS NOT NULL
)
--Incorect synstax near SET.
SET @sql = 'INSERT INTO '+ QUOTENAME(@tableName) + '(accountId, date, cost)
(SELECT cte.id, ms.date, ms.cost
FROM #stats ms
INNER JOIN CTE cte ON ms.accountNumber = cte.key4)';
EXECUTE sp_executesql @sql;
DROP TABLE #stats;
END
答案 0 :(得分:1)
将表名作为参数传递
使用QUOTENAME() Function
在表名周围放置方括号,以明确告诉sql server它是一个像这样的Sql Server对象名。
DECLARE @Sql NVARCHAR(MAX);
SET @Sql = N';WITH CTE(id, key4) AS (
SELECT A.id, A.[key4]
FROM VA A (NOLOCK)
WHERE A.id = @accountID
UNION ALL
SELECT A.id, A.[key4]
FROM VA A (NOLOCK)
INNER JOIN CTE ON (CTE.id = A.MAID)
WHERE A.key4 IS NOT NULL
)
INSERT INTO ' + QUOTENAME(@tableName) +' (accountId, date, cost)
SELECT cte.id, ms.date, ms.cost
FROM #stats ms
INNER JOIN CTE cte ON ms.accountNumber = cte.key4;'
EXECUTE sp_executesql @Sql
使用QUOTENAME()函数可以保护您免受sql injection attack
的攻击。您也不需要在select语句周围使用括号。
此外,您应该避免为存储过程名称使用sp_
前缀。 Read Here为什么。
使用IF..ELSE阻止
IF (Some_Condition IS TRUE)
BEGIN
/* Insert Statement For Table One*/ --<-- No need to use table Names as variable
END -- just hardcode the table names in your
ELSE -- Insert Statements
BEGIN
/* Insert Statement For Table Two*/
END
答案 1 :(得分:0)
您是否注意到您在声明中错过了逗号。
ALTER PROCEDURE [dbo].[sp_importStats] (
@accountID BIGINT,
@csvFileName VARCHAR (1024),
@csvFormatFileName VARCHAR (1024),---comma missing here
@tableName VARCHAR(256))