T-Sql

生成 INSERT 列表,但僅適用於不可為空的列

  • January 9, 2018

我目前使用 SSMS 2016 作為客戶端並擁有一個 Azure SQL 數據庫(也是 2008 r2)。

但我正在尋找一種創建自定義模板的方法,以便僅使用具有“非空”的欄位準備插入語句

在此處輸入圖像描述

如果我右鍵點擊一個表並生成一個插入語句,我會得到一個很長的所有可能列的列表。我希望看到需要填充的最少列。有沒有辦法為 ssms 生成這樣的 sql 腳本?還是只有其他數據庫工具才能做到這一點?

我有一個超過 30 列的表,並且允許大約 90% 為空,所以我更喜歡生成的插入語句只包含我真正需要填寫的 10% 的列。

您無法更改 UI 的執行方式,您必須自己編寫這種程式碼,抱歉。但在簡單的情況下,這很容易自己生成sys.dm_exec_describe_first_result_set(將此程式碼保存為模板或片段):

DECLARE @table nvarchar(261) = N'dbo.YourTableName';

;WITH x AS 
(
 SELECT name, system_type_name, 
   column_ordinal = ROW_NUMBER() OVER (ORDER BY column_ordinal)
 FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM ' + @table, N'', 0)
 WHERE is_nullable = 0
   AND is_identity_column = 0
   AND is_computed_column = 0
)
SELECT N'INSERT ' + @table + N'(', N'--', column_ordinal = 0
UNION ALL
SELECT CHAR(13) + CHAR(10) + CASE column_ordinal 
 WHEN 1 THEN N'' ELSE N',' END + QUOTENAME(name), 
 N'--', column_ordinal
FROM x
UNION ALL
SELECT N'
) VALUES (', N'--', 1000
UNION ALL
SELECT CHAR(13) + CHAR(10) + CASE column_ordinal 
 WHEN 1 THEN N'' ELSE N',' END
 + N'<' + name + N', ' +system_type_name + N',>',
 N'--', 1000 + column_ordinal
FROM x
UNION ALL
SELECT N'
);', N'--', 10000
ORDER BY column_ordinal;

這會忽略標識列和任何計算列,但視圖不會告訴您其他資訊,例如具有預設值的非空列或 rowguidcol 列,這些也應該不在您的語句中。

一般而言,以下解決方案可能更合適,因為您仍在使用 SQL Server 2008 R2(該視圖是在 SQL Server 2012 中引入的)。它處理 rowguidcol 和預設值,但由於生成友好的類型所需的工作而更加冗長。

DECLARE @table nvarchar(261) = N'dbo.YourTableName';

;WITH x AS 
(
 SELECT [column] = c.name, [type] = t.name, t.system_type_id, 
   t.user_type_id, c.max_length, c.precision, c.scale, 
   column_ordinal = ROW_NUMBER() OVER (ORDER BY c.column_id)
 FROM sys.columns AS c 
 INNER JOIN sys.types AS t
   ON c.system_type_id = t.system_type_id
  AND t.user_type_id = CASE -- filter out false sysname
    WHEN c.system_type_id = 231 THEN CASE 
      WHEN c.max_length = 256 THEN c.user_type_id 
      ELSE c.system_type_id END
    ELSE c.user_type_id END
 WHERE [object_id] = OBJECT_ID(@table)
   AND c.is_nullable       = 0 
   AND c.is_identity       = 0 
   AND c.is_computed       = 0
   AND c.is_rowguidcol     = 0 
   AND c.default_object_id = 0
)
SELECT N'INSERT ' + @table + N'(', N'--', column_ordinal = 0
UNION ALL 
SELECT CASE column_ordinal WHEN 1 THEN N'' ELSE N',' END
   + QUOTENAME([column]), N'--', column_ordinal 
 FROM x
UNION ALL SELECT N') VALUES(', N'--', 1000
UNION ALL
SELECT CASE column_ordinal WHEN 1 THEN N'' ELSE N',' END
   + N'<' + [column] + N',' + [type] + CASE 
   WHEN system_type_id IN (106,108)
   THEN N'(' + CONVERT(varchar(11), precision)
      + N',' + CONVERT(varchar(11), scale) + N')'
   WHEN system_type_id IN (59,62)
   THEN N'(' + CONVERT(varchar(11), precision) + N')'
   WHEN system_type_id IN (41,42,43)
   THEN N'(' + CONVERT(varchar(11), scale) + N')'
   WHEN system_type_id IN (167,175,239,231,165,173) AND user_type_id <> 256
   THEN N'(' + CASE max_length WHEN -1 THEN N'max' ELSE 
     CONVERT(varchar(11), max_length / CASE 
       WHEN system_type_id IN (231,239) THEN 2 ELSE 1 END) END + ')'
   ELSE N''
  END
   + N',>', N'--', 1000 + column_ordinal
 FROM x
UNION ALL SELECT N');', N'--', 10000
ORDER BY column_ordinal;

請注意,在這兩種情況下,我都嘗試完全匹配 SSMS 的輸出,每個製表符和輸入除外。我不認為他們的輸出在所有方面都有意義,但是您可以根據自己的喜好對其進行調整。

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