Sql-Server

帶有表名、列和值參數的 INSERT INTO 語句?

  • January 9, 2018

是否有可能有一個看起來像這樣的 SP:

DECLARE @tableName = null;
DECLARE @cols = null;
DECLARE @values = null;

INSERT INTO @tableName @cols @values;

結果查詢如下所示:

INSERT INTO <table name> (<set of column names>) VALUES (<set of corresponding values>);

我的案例是我將 Excel 數據解析到數據庫中,即“X 型”的單個工作簿等同於該數據庫中的單行。這些工作簿是從模板中填寫的,因此數據格式非常固定。為了解析數據,我在工作簿中創建了一個名為“ DATA ”之類的工作表,如下所示:

tableName | attributeName | attributeValue | .. plus some config stuff
People    | Firstname     | Johnny         | etc
People    | Lastname      | Heinz          | etc
People    | Firstname     | Sam            | etc
People    | Lastname      | Smith          | etc

這將等同於數據庫表中的兩行(通過對特定表People重複來辨識多行)。attributeNames

這需要動態 SQL 的原因是:

  1. 我希望這適用於數據庫中的任何表
  2. 在解析之前我不知道特定表有多少列
  1. 您不能參數化表名或列名 - 您必須使用動態 SQL。
  2. 您還應該傳遞表的schema
  3. 您應該驗證表名和列名。表名很容易檢查,但對於列名,我們將使用這個函式:
CREATE FUNCTION dbo.ParseColumnList
(
 @List NVARCHAR(MAX)
)
RETURNS TABLE
AS
 RETURN   
 (
   SELECT i, 
     c = LTRIM(CONVERT(SYSNAME, SUBSTRING(@List, i, 
         CHARINDEX(',', @List + ',', i) - i)))
   FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) 
         FROM sys.all_columns) AS n(i)
   WHERE i <= LEN(@List) AND SUBSTRING(',' + @List, i, 1) = ','
 );
  1. 您應該對參數值使用強類型參數,以保護自己免受 SQL 注入漏洞的侵害。了解這些參數值的來源將有助於進一步完善此解決方案,但現在您只需要盲目地附加值列表並希望獲得最好的結果:
CREATE PROCEDURE dbo.DealersChoice
 @TableSchema   sysname,
 @TableName     sysname,
 @ColumnList    nvarchar(max),
 @ParamValues   nvarchar(max)
AS
BEGIN
 SET NOCOUNT ON;

 IF NOT EXISTS ( -- make sure table exists:
   SELECT 1 FROM sys.tables AS t
     INNER JOIN sys.schemas AS s
     ON t.[schema_id] = s.[schema_id]
     WHERE t.name = QUOTENAME(@TableName)
     AND s.name = QUOTENAME(@TableSchema)
 )
 BEGIN -- raise an appropriate error here
   RETURN;
 END

 IF EXISTS ( -- make sure columns exist:
   SELECT 1 FROM dbo.ParseColumnList(@ColumnList) AS f
     LEFT OUTER JOIN sys.columns AS c ON f.c = c.name
     WHERE c.[object_id] = OBJECT_ID(QUOTENAME(@TableSchema)
       + N'.' + QUOTENAME(@TableName))
   WHERE c.name IS NULL
 )
 BEGIN -- raise appropriate error
   RETURN;
 END

 DECLARE @sql nvarchar(max) = N'INSERT '
   + QUOTENAME(@TableSchema) + N'.' + QUOTENAME(@TableName)
   + N' (' + @ColumnList + N') VALUES(' + @ParamValues + N');';

 EXEC sys.sp_executesql @sql;
END

我不確定您是如何建構@ParamValues參數的,但是如果您在其中嵌入了字元串定界符(例如5, 'foo', '20160206'),則需要將它們加倍使其成為5, ''foo'', ''20160206''-當您有字元串時,這將成為一個挑戰O'Brien-其中一個為什麼您應該使用正確的參數而不是將一個大字元串與所有值連接起來的原因有很多。

請參閱以下內容:

引用自:https://dba.stackexchange.com/questions/163352