Sql-Server
帶有表名、列和值參數的 INSERT INTO 語句?
是否有可能有一個看起來像這樣的 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 的原因是:
- 我希望這適用於數據庫中的任何表
- 在解析之前我不知道特定表有多少列
- 您不能參數化表名或列名 - 您必須使用動態 SQL。
- 您還應該傳遞表的schema。
- 您應該驗證表名和列名。表名很容易檢查,但對於列名,我們將使用這個函式:
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) = ',' );
- 您應該對參數值使用強類型參數,以保護自己免受 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
-其中一個為什麼您應該使用正確的參數而不是將一個大字元串與所有值連接起來的原因有很多。請參閱以下內容: