開發資料庫應用時,為每張表手寫 CRUD 預存程序既繁瑣又易出錯。本文提供兩個系統預存程序 sp_GenInsert、sp_GenUpdate,可依資料表中繼資料自動產生標準化的 Insert/Update 程式碼,大幅提升開發效率。
EXEC sp_GenInsert '資料表名', '產生的預存程序名';
-- 範例
EXEC sp_GenInsert 'Employees', 'INS_Employees';
CREATE PROCEDURE INS_Employees
@LastName NVARCHAR(20),
@FirstName NVARCHAR(10),
@Title NVARCHAR(30),
@TitleOfCourtesy NVARCHAR(25),
@BirthDate DATETIME,
@HireDate DATETIME,
@Address NVARCHAR(60),
@City NVARCHAR(15),
@Region NVARCHAR(15),
@PostalCode NVARCHAR(10),
@Country NVARCHAR(15),
@HomePhone NVARCHAR(24),
@Extension NVARCHAR(4),
@Photo IMAGE,
@Notes NTEXT,
@ReportsTo INT,
@PhotoPath NVARCHAR(255)
AS
INSERT INTO Employees (LastName, FirstName, Title, TitleOfCourtesy,
BirthDate, HireDate, Address, City, Region, PostalCode, Country,
HomePhone, Extension, Photo, Notes, ReportsTo, PhotoPath)
VALUES (@LastName, @FirstName, @Title, @TitleOfCourtesy,
@BirthDate, @HireDate, @Address, @City, @Region, @PostalCode, @Country,
@HomePhone, @Extension, @Photo, @Notes, @ReportsTo, @PhotoPath);
GO
IDENTITY 欄位,產生的程式碼會包含 SET IDENTITY_INSERT ON,需手動移除或視需求保留。master 資料庫且加上 sp_ 前綴,即可跨資料庫呼叫。EXEC sp_GenUpdate '資料表名', '主鍵欄位', '產生的預存程序名';
-- 範例
EXEC sp_GenUpdate 'Employees', 'EmployeeID', 'UPD_Employees';
CREATE PROCEDURE UPD_Employees
@EmployeeID INT,
@LastName NVARCHAR(20),
@FirstName NVARCHAR(10),
@Title NVARCHAR(30),
@TitleOfCourtesy NVARCHAR(25),
@BirthDate DATETIME,
@HireDate DATETIME,
@Address NVARCHAR(60),
@City NVARCHAR(15),
@Region NVARCHAR(15),
@PostalCode NVARCHAR(10),
@Country NVARCHAR(15),
@HomePhone NVARCHAR(24),
@Extension NVARCHAR(4),
@Photo IMAGE,
@Notes NTEXT,
@ReportsTo INT,
@PhotoPath NVARCHAR(255)
AS
UPDATE Employees SET
LastName = @LastName,
FirstName = @FirstName,
Title = @Title,
TitleOfCourtesy = @TitleOfCourtesy,
BirthDate = @BirthDate,
HireDate = @HireDate,
Address = @Address,
City = @City,
Region = @Region,
PostalCode = @PostalCode,
Country = @Country,
HomePhone = @HomePhone,
Extension = @Extension,
Photo = @Photo,
Notes = @Notes,
ReportsTo = @ReportsTo,
PhotoPath = @PhotoPath
WHERE EmployeeID = @EmployeeID;
GO
USE master; GO
CREATE PROCEDURE sp_GenInsert
@TableName VARCHAR(130),
@ProcedureName VARCHAR(130)
AS
SET NOCOUNT ON;
DECLARE @maxcol INT, @TableID INT;
SET @TableID = OBJECT_ID(@TableName);
SELECT @maxcol = MAX(colorder) FROM syscolumns WHERE id = @TableID;
SELECT 'CREATE PROCEDURE ' + RTRIM(@ProcedureName) AS [text], 0 AS colorder INTO #TempProc
UNION ALL
SELECT '@' + c.name + ' ' + t.name +
CASE WHEN t.name IN ('binary','char','nchar','nvarchar','varbinary','varchar')
THEN '(' + RTRIM(CONVERT(CHAR(4), c.length)) + ')'
ELSE '' END +
CASE WHEN c.colorder < @maxcol THEN ',' ELSE ' ' END,
c.colorder
FROM syscolumns c JOIN systypes t ON c.xtype = t.xtype
WHERE c.id = @TableID AND t.name <> 'sysname'
UNION ALL
SELECT 'AS', @maxcol + 1
UNION ALL
SELECT 'INSERT INTO ' + @TableName, @maxcol + 2
UNION ALL
SELECT '(', @maxcol + 3
UNION ALL
SELECT c.name + CASE WHEN c.colorder < @maxcol THEN ',' ELSE ' ' END,
c.colorder + @maxcol + 3
FROM syscolumns c JOIN systypes t ON c.xtype = t.xtype
WHERE c.id = @TableID AND t.name <> 'sysname'
UNION ALL
SELECT ')', @maxcol * 2 + 4
UNION ALL
SELECT 'VALUES (', @maxcol * 2 + 5
UNION ALL
SELECT '@' + c.name + CASE WHEN c.colorder < @maxcol THEN ',' ELSE ' ' END,
c.colorder + @maxcol * 2 + 5
FROM syscolumns c JOIN systypes t ON c.xtype = t.xtype
WHERE c.id = @TableID AND t.name <> 'sysname'
UNION ALL
SELECT ')', @maxcol * 3 + 6
ORDER BY colorder;
GO
CREATE PROCEDURE sp_GenUpdate
@TableName VARCHAR(130),
@PrimaryKey VARCHAR(130),
@ProcedureName VARCHAR(130)
AS
SET NOCOUNT ON;
DECLARE @maxcol INT, @TableID INT;
SET @TableID = OBJECT_ID(@TableName);
SELECT @maxcol = MAX(colorder) FROM syscolumns WHERE id = @TableID;
-- 參數宣告、AS、UPDATE、SET 同 sp_GenInsert,最後加上:
UNION ALL
SELECT @PrimaryKey + ' = @' + @PrimaryKey, @maxcol * 2 + 5 -- WHERE 條件
ORDER BY colorder;
GO
@ExcludeColumns VARCHAR(8000) 參數,跳過 timestamp、rowversion、計算欄位timestamp 欄位,產出 WHERE PK = @PK AND ts = @tsModifiedBy = SUSER_SNAME(), ModifiedDate = GETDATE()xp_cmdshell + bcp 直接產出 .sql 檔納入版控將 sp_GenInsert/sp_GenUpdate 部署至 master,新增/修改表結構後一鍵重產預存程序,配合上述客製化,可構建輕量級的「資料庫優先」開發流程,讓團隊專注於業務邏輯而非重複性 CRUD 程式碼。