Speed up development by automatically generating commmon stored procedure definitions
There are numerous times when developing a new web or windows application when you will need to write some stored procedures for the basic CRUD (Create, Read, Update, Delete) operations for each table in your database.For instance a table will need a stored procedure defined for Inserting a record into it, deleting a specified record from it, selecting a specified record from it and selecting all records from it. Writing these Stored Procedures can be very repetitive and time consuming. Once you are familiar with how to write these procedures it can become a chore having to mindlessly type them all out.
The SQL script provided in this article generates 4 Stored Procedure definitions for each specified table(s) in your database. The auto generated Procedure definitions achieve the following:
- 1) List all records in the table (proc name suffix of _lst)
- 2) Get a specific record from the table (proc name suffix of _sel)
- 3) UPDATE or INSERT (UPSERT) a row- (proc name suffix of _ups)
- 4) DELETE a specified row - (proc name suffix of _del)
dbo.udp_Location_lst
dbo.udp_Location_sel
dbo.udp_Location_ups
dbo.udp_Location_del
The stored procedure definitions can either be printed to the screen for you to copy and paste OR executed to actually create the Stored Procs. The stored proc names are prefixed with udp_ (user defined procedure) to avoid conflicts with any existing system stored procs.
The script uses the INFORMATION_SCHEMA tables to obtain information about the tables and columns in the specified database. The INFORMATION_SCHEMA is a SQL-92 standard that can be used in most major database systems including ORACLE and SQL SERVER.
Assumptions made by the script
This script assumes that the primary key will be used for selecting, updating and deleting an individual record and that the primary key is the first column in the table. The script also assumes if the primary key is an integer then it is an IDENTITY (autonumber) field.This script is not suitable for the link tables in the middle of a many to many relationship.
After the script has run you will need to add an ORDER BY clause into the '_lst' procedures according to your needs / required sort order.
The script assumes you have set valid values for the config variables config section at the top of the script
You can set the script to run on all user defined tables in your database OR on a single specified table.
The script can be downloaded here
Example output
The following is the printed output from the script when it was set to run on the 'Customers' table of the 'Northwind' sample database that is provided with SQL Server 2000.CREATE PROC [dbo].[udp_Orders_lst] AS SET NOCOUNT ON SELECT [OrderID], [CustomerID], [EmployeeID], [OrderDate], [RequiredDate], [ShippedDate], [ShipVia], [Freight], [ShipName], [ShipAddress], [ShipCity], [ShipRegion], [ShipPostalCode], [ShipCountry] FROM Orders SET NOCOUNT OFF GO CREATE PROC [dbo].[udp_Orders_sel] @OrderID int AS SET NOCOUNT ON SELECT [OrderID], [CustomerID], [EmployeeID], [OrderDate], [RequiredDate], [ShippedDate], [ShipVia], [Freight], [ShipName], [ShipAddress], [ShipCity], [ShipRegion], [ShipPostalCode], [ShipCountry] FROM Orders WHERE [OrderID] = @OrderID SET NOCOUNT OFF GO CREATE PROC [dbo].[udp_Orders_ups] @OrderID int, @CustomerID nchar(5), @EmployeeID int, @OrderDate datetime, @RequiredDate datetime, @ShippedDate datetime, @ShipVia int, @Freight money, @ShipName nvarchar(40), @ShipAddress nvarchar(60), @ShipCity nvarchar(15), @ShipRegion nvarchar(15), @ShipPostalCode nvarchar(10), @ShipCountry nvarchar(15) AS SET NOCOUNT ON IF @OrderID = 0 BEGIN INSERT INTO Orders ( [CustomerID], [EmployeeID], [OrderDate], [RequiredDate], [ShippedDate], [ShipVia], [Freight], [ShipName], [ShipAddress], [ShipCity], [ShipRegion], [ShipPostalCode], [ShipCountry] ) VALUES ( @CustomerID, @EmployeeID, @OrderDate, @RequiredDate, @ShippedDate, @ShipVia, @Freight, @ShipName, @ShipAddress, @ShipCity, @ShipRegion, @ShipPostalCode, @ShipCountry ) SELECT SCOPE_IDENTITY() As NewID END ELSE BEGIN UPDATE Orders SET [CustomerID] = @CustomerID, [EmployeeID] = @EmployeeID, [OrderDate] = @OrderDate, [RequiredDate] = @RequiredDate, [ShippedDate] = @ShippedDate, [ShipVia] = @ShipVia, [Freight] = @Freight, [ShipName] = @ShipName, [ShipAddress] = @ShipAddress, [ShipCity] = @ShipCity, [ShipRegion] = @ShipRegion, [ShipPostalCode] = @ShipPostalCode, [ShipCountry] = @ShipCountry WHERE [OrderID] = @OrderID END SET NOCOUNT OFF GO CREATE PROC [dbo].[udp_Orders_del] @OrderID int AS SET NOCOUNT ON DELETE FROM Orders WHERE [OrderID] = @OrderID SET NOCOUNT OFF GOYou can see that the script formats the procedures nicely making it easy to follow the code in them and providing a consistent approach to naming conventions and formatting which helps speed up development time.
Conclusion
Whilst you can generate automatic 'SELECT / INSERT / UPDATE / DELETE statements using SQL Server Enterprise manager or SQL Server Management Studio these do not script the procedure definitions or parameter definitions / variable names used in the stored procs. The script provided can save you a great deal of time when you need to write repetitive CRUD stored procedures. Enjoy!.With thanks from
http://www.sqlbook.com/SQL-Server/Auto-generate-CRUD-Stored-Procedures-40.aspx
Here's the Script
-- ######################################################### -- Author: www.sqlbook.com -- Copyright: (c) www.sqlbook.com. You are free to use and redistribute -- this script as long as this comments section with the -- author and copyright details are not altered. -- Purpose: For a specified user defined table (or all user defined -- tables) in the database this script generates 4 Stored -- Procedure definitions with different Procedure name -- suffixes: -- 1) List all records in the table (suffix of _lst) -- 2) Get a specific record from the table (suffix of _sel) -- 3) UPDATE or INSERT (UPSERT) - (suffix of _ups) -- 4) DELETE a specified row - (suffix of _del) -- e.g. For a table called location the script will create -- procedure definitions for the following procedures: -- dbo.udp_Location_lst -- dbo.udp_Location_sel -- dbo.udp_Location_ups -- dbo.udp_Location_del -- Notes: The stored procedure definitions can either be printed -- to the screen or executed using EXEC sp_ExecuteSQL. -- The stored proc names are prefixed with udp_ to avoid -- conflicts with system stored procs. -- Assumptions: - This script assumes that the primary key is the first -- column in the table and that if the primary key is -- an integer then it is an IDENTITY (autonumber) field. -- - This script is not suitable for the link tables -- in the middle of a many to many relationship. -- - After the script has run you will need to add -- an ORDER BY clause into the '_lst' procedures -- according to your needs / required sort order. -- - Assumes you have set valid values for the -- config variables in the section immediately below -- ######################################################### -- ########################################################## /* SET CONFIG VARIABLES THAT ARE USED IN SCRIPT */ -- ########################################################## -- Do we want to generate the SP definitions for every user defined -- table in the database or just a single specified table? -- Assign a blank string - '' for all tables or the table name for -- a single table. DECLARE @GenerateProcsFor varchar(100) SET @GenerateProcsFor = 'Orders' --SET @GenerateProcsFor = '' -- which database do we want to create the procs for? -- Change both the USE and SET lines below to set the datbase name -- to the required database. USE Northwind DECLARE @DatabaseName varchar(100) SET @DatabaseName = 'Northwind' -- do we want the script to print out the CREATE PROC statements -- or do we want to execute them to actually create the procs? -- Assign a value of either 'Print' or 'Execute' DECLARE @PrintOrExecute varchar(10) SET @PrintOrExecute = 'Print' -- Is there a table name prefix i.e. 'tbl_' which we don't want -- to include in our stored proc names? DECLARE @TablePrefix varchar(10) SET @TablePrefix = 'tbl_' -- For our '_lst' and '_sel' procedures do we want to -- do SELECT * or SELECT [ColumnName,]... -- Assign a value of either 1 or 0 DECLARE @UseSelectWildCard bit SET @UseSelectWildCard = 0 -- ########################################################## /* END SETTING OF CONFIG VARIABLE -- do not edit below this line */ -- ########################################################## -- DECLARE CURSOR containing all columns from user defined tables -- in the database DECLARE TableCol Cursor FOR SELECT c.TABLE_SCHEMA, c.TABLE_NAME, c.COLUMN_NAME, c.DATA_TYPE, c.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.Columns c INNER JOIN INFORMATION_SCHEMA.Tables t ON c.TABLE_NAME = t.TABLE_NAME WHERE t.Table_Catalog = @DatabaseName AND t.TABLE_TYPE = 'BASE TABLE' ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION -- Declare variables which will hold values from cursor rows DECLARE @TableSchema varchar(100), @TableName varchar(100) DECLARE @ColumnName varchar(100), @DataType varchar(30) DECLARE @CharLength int DECLARE @ColumnNameCleaned varchar(100) -- Declare variables which will track what table we are -- creating Stored Procs for DECLARE @CurrentTable varchar(100) DECLARE @FirstTable bit DECLARE @FirstColumnName varchar(100) DECLARE @FirstColumnDataType varchar(30) DECLARE @ObjectName varchar(100) -- this is the tablename with the -- specified tableprefix lopped off. DECLARE @TablePrefixLength int -- init vars SET @CurrentTable = '' SET @FirstTable = 1 SET @TablePrefixLength = Len(@TablePrefix) -- Declare variables which will hold the queries we are building use unicode -- data types so that can execute using sp_ExecuteSQL DECLARE @LIST nvarchar(4000), @UPSERT nvarchar(4000) DECLARE @SELECT nvarchar(4000), @INSERT nvarchar(4000), @INSERTVALUES varchar(4000) DECLARE @UPDATE nvarchar(4000), @DELETE nvarchar(4000) -- open the cursor OPEN TableCol -- get the first row of cursor into variables FETCH NEXT FROM TableCol INTO @TableSchema, @TableName, @ColumnName, @DataType, @CharLength -- loop through the rows of the cursor WHILE @@FETCH_STATUS = 0 BEGIN SET @ColumnNameCleaned = Replace(@ColumnName, ' ', '') -- is this a new table? IF @TableName <> @CurrentTable BEGIN -- if is the end of the last table IF @CurrentTable <> '' BEGIN IF @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable BEGIN -- first add any syntax to end the statement -- _lst SET @LIST = @List + Char(13) + 'FROM ' + @CurrentTable + Char(13) SET @LIST = @LIST + Char(13) + Char(13) + 'SET NOCOUNT OFF' + Char(13) + Char(13) SET @LIST = @LIST + Char(13) -- _sel SET @SELECT = @SELECT + Char(13) + 'FROM ' + @CurrentTable + Char(13) SET @SELECT = @SELECT + 'WHERE [' + @FirstColumnName + '] = @' + Replace(@FirstColumnName, ' ', '') + Char(13) SET @SELECT = @SELECT + Char(13) + Char(13) + 'SET NOCOUNT OFF' + Char(13) + Char(13) SET @SELECT = @SELECT + Char(13) -- UPDATE (remove trailing comma and append the WHERE clause) SET @UPDATE = SUBSTRING(@UPDATE, 0, LEN(@UPDATE)- 1) + Char(13) + Char(9) + 'WHERE [' + @FirstColumnName + '] = @' + Replace(@FirstColumnName, ' ', '') + Char(13) -- INSERT SET @INSERT = SUBSTRING(@INSERT, 0, LEN(@INSERT) - 1) + Char(13) + Char(9) + ')' + Char(13) SET @INSERTVALUES = SUBSTRING(@INSERTVALUES, 0, LEN(@INSERTVALUES) -1) + Char(13) + Char(9) + ')' SET @INSERT = @INSERT + @INSERTVALUES -- _ups SET @UPSERT = @UPSERT + Char(13) + 'AS' + Char(13) SET @UPSERT = @UPSERT + 'SET NOCOUNT ON' + Char(13) IF @FirstColumnDataType IN ('int', 'bigint', 'smallint', 'tinyint', 'float', 'decimal') BEGIN SET @UPSERT = @UPSERT + 'IF @' + Replace(@FirstColumnName, ' ', '') + ' = 0 BEGIN' + Char(13) END ELSE BEGIN SET @UPSERT = @UPSERT + 'IF @' + Replace(@FirstColumnName, ' ', '') + ' = '''' BEGIN' + Char(13) END SET @UPSERT = @UPSERT + ISNULL(@INSERT, '') + Char(13) SET @UPSERT = @UPSERT + Char(9) + 'SELECT SCOPE_IDENTITY() As InsertedID' + Char(13) SET @UPSERT = @UPSERT + 'END' + Char(13) SET @UPSERT = @UPSERT + 'ELSE BEGIN' + Char(13) SET @UPSERT = @UPSERT + ISNULL(@UPDATE, '') + Char(13) SET @UPSERT = @UPSERT + 'END' + Char(13) + Char(13) SET @UPSERT = @UPSERT + 'SET NOCOUNT OFF' + Char(13) + Char(13) SET @UPSERT = @UPSERT + Char(13) -- _del -- delete proc completed already -- -------------------------------------------------- -- now either print the SP definitions or -- execute the statements to create the procs -- -------------------------------------------------- IF @PrintOrExecute <> 'Execute' BEGIN PRINT @LIST PRINT @SELECT PRINT @UPSERT PRINT @DELETE END ELSE BEGIN EXEC sp_Executesql @LIST EXEC sp_Executesql @SELECT EXEC sp_Executesql @UPSERT EXEC sp_Executesql @DELETE END END -- end @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable END -- update the value held in @CurrentTable SET @CurrentTable = @TableName SET @FirstColumnName = @ColumnName SET @FirstColumnDataType = @DataType IF @TablePrefixLength > 0 BEGIN IF SUBSTRING(@CurrentTable, 1, @TablePrefixLength) = @TablePrefix BEGIN --PRINT Char(13) + 'DEBUG: OBJ NAME: ' + RIGHT(@CurrentTable, LEN(@CurrentTable) - @TablePrefixLength) SET @ObjectName = RIGHT(@CurrentTable, LEN(@CurrentTable) - @TablePrefixLength) END ELSE BEGIN SET @ObjectName = @CurrentTable END END ELSE BEGIN SET @ObjectName = @CurrentTable END IF @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable BEGIN -- ---------------------------------------------------- -- now start building the procedures for the next table -- ---------------------------------------------------- -- _lst SET @LIST = 'CREATE PROC [dbo].[udp_' + @ObjectName + '_lst]' + Char(13) SET @LIST = @LIST + 'AS' + Char(13) SET @LIST = @LIST + 'SET NOCOUNT ON' + Char(13) IF @UseSelectWildcard = 1 BEGIN SET @LIST = @LIST + Char(13) + 'SELECT * ' END ELSE BEGIN SET @LIST = @LIST + Char(13) + 'SELECT [' + @ColumnName + ']' END -- _sel SET @SELECT = 'CREATE PROC [dbo].[udp_' + @ObjectName + '_sel]' + Char(13) SET @SELECT = @SELECT + Char(9) + '@' + @ColumnNameCleaned + ' ' + @DataType IF @DataType IN ('varchar', 'nvarchar', 'char', 'nchar') BEGIN SET @SELECT = @SELECT + '(' + CAST(@CharLength As varchar(10)) + ')' END SET @SELECT = @SELECT + Char(13) + 'AS' + Char(13) SET @SELECT = @SELECT + 'SET NOCOUNT ON' + Char(13) IF @UseSelectWildcard = 1 BEGIN SET @SELECT = @SELECT + Char(13) + 'SELECT * ' END ELSE BEGIN SET @SELECT = @SELECT + Char(13) + 'SELECT [' + @ColumnName + ']' END -- _ups SET @UPSERT = 'CREATE PROC [dbo].[udp_' + @ObjectName + '_ups]' + Char(13) SET @UPSERT = @UPSERT + Char(13) + Char(9) + '@' + @ColumnNameCleaned + ' ' + @DataType IF @DataType IN ('varchar', 'nvarchar', 'char', 'nchar') BEGIN SET @UPSERT = @UPSERT + '(' + CAST(@CharLength As Varchar(10)) + ')' END -- UPDATE SET @UPDATE = Char(9) + 'UPDATE ' + @TableName + ' SET ' + Char(13) -- INSERT -- don't add first column to insert if it is an -- integer (assume autonumber) SET @INSERT = Char(9) + 'INSERT INTO ' + @TableName + ' (' + Char(13) SET @INSERTVALUES = Char(9) + 'VALUES (' + Char(13) IF @FirstColumnDataType NOT IN ('int', 'bigint', 'smallint', 'tinyint') BEGIN SET @INSERT = @INSERT + Char(9) + Char(9) + '[' + @ColumnName + '],' + Char(13) SET @INSERTVALUES = @INSERTVALUES + Char(9) + Char(9) + '@' + @ColumnNameCleaned + ',' + Char(13) END -- _del SET @DELETE = 'CREATE PROC [dbo].[udp_' + @ObjectName + '_del]' + Char(13) SET @DELETE = @DELETE + Char(9) + '@' + @ColumnNameCleaned + ' ' + @DataType IF @DataType IN ('varchar', 'nvarchar', 'char', 'nchar') BEGIN SET @DELETE = @DELETE + '(' + CAST(@CharLength As Varchar(10)) + ')' END SET @DELETE = @DELETE + Char(13) + 'AS' + Char(13) SET @DELETE = @DELETE + 'SET NOCOUNT ON' + Char(13) + Char(13) SET @DELETE = @DELETE + 'DELETE FROM ' + @TableName + Char(13) SET @DELETE = @DELETE + 'WHERE [' + @ColumnName + '] = @' + @ColumnNameCleaned + Char(13) SET @DELETE = @DELETE + Char(13) + 'SET NOCOUNT OFF' + Char(13) SET @DELETE = @DELETE + Char(13) END -- end @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable END ELSE BEGIN IF @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable BEGIN -- is the same table as the last row of the cursor -- just append the column -- _lst IF @UseSelectWildCard = 0 BEGIN SET @LIST = @LIST + ', ' + Char(13) + Char(9) + '[' + @ColumnName + ']' END -- _sel IF @UseSelectWildCard = 0 BEGIN SET @SELECT = @SELECT + ', ' + Char(13) + Char(9) + '[' + @ColumnName + ']' END -- _ups SET @UPSERT = @UPSERT + ',' + Char(13) + Char(9) + '@' + @ColumnNameCleaned + ' ' + @DataType IF @DataType IN ('varchar', 'nvarchar', 'char', 'nchar') BEGIN SET @UPSERT = @UPSERT + '(' + CAST(@CharLength As varchar(10)) + ')' END -- UPDATE SET @UPDATE = @UPDATE + Char(9) + Char(9) + '[' + @ColumnName + '] = @' + @ColumnNameCleaned + ',' + Char(13) -- INSERT SET @INSERT = @INSERT + Char(9) + Char(9) + '[' + @ColumnName + '],' + Char(13) SET @INSERTVALUES = @INSERTVALUES + Char(9) + Char(9) + '@' + @ColumnNameCleaned + ',' + Char(13) -- _del -- delete proc completed already END -- end @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable' END -- fetch next row of cursor into variables FETCH NEXT FROM TableCol INTO @TableSchema, @TableName, @ColumnName, @DataType, @CharLength END -- ---------------- -- clean up cursor -- ---------------- CLOSE TableCol DEALLOCATE TableCol -- ------------------------------------------------ -- repeat the block of code from within the cursor -- So that the last table has its procs completed -- and printed / executed -- ------------------------------------------------ -- if is the end of the last table IF @CurrentTable <> '' BEGIN IF @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable BEGIN -- first add any syntax to end the statement -- _lst SET @LIST = @List + Char(13) + 'FROM ' + @CurrentTable + Char(13) SET @LIST = @LIST + Char(13) + Char(13) + 'SET NOCOUNT OFF' + Char(13) SET @LIST = @LIST + Char(13) -- _sel SET @SELECT = @SELECT + Char(13) + 'FROM ' + @CurrentTable + Char(13) SET @SELECT = @SELECT + 'WHERE [' + @FirstColumnName + '] = @' + Replace(@FirstColumnName, ' ', '') + Char(13) SET @SELECT = @SELECT + Char(13) + Char(13) + 'SET NOCOUNT OFF' + Char(13) SET @SELECT = @SELECT + Char(13) -- UPDATE (remove trailing comma and append the WHERE clause) SET @UPDATE = SUBSTRING(@UPDATE, 0, LEN(@UPDATE)- 1) + Char(13) + Char(9) + 'WHERE [' + @FirstColumnName + '] = @' + Replace(@FirstColumnName, ' ', '') + Char(13) -- INSERT SET @INSERT = SUBSTRING(@INSERT, 0, LEN(@INSERT) - 1) + Char(13) + Char(9) + ')' + Char(13) SET @INSERTVALUES = SUBSTRING(@INSERTVALUES, 0, LEN(@INSERTVALUES) -1) + Char(13) + Char(9) + ')' SET @INSERT = @INSERT + @INSERTVALUES -- _ups SET @UPSERT = @UPSERT + Char(13) + 'AS' + Char(13) SET @UPSERT = @UPSERT + 'SET NOCOUNT ON' + Char(13) IF @FirstColumnDataType IN ('int', 'bigint', 'smallint', 'tinyint', 'float', 'decimal') BEGIN SET @UPSERT = @UPSERT + 'IF @' + Replace(@FirstColumnName, ' ', '') + ' = 0 BEGIN' + Char(13) END ELSE BEGIN SET @UPSERT = @UPSERT + 'IF @' + Replace(@FirstColumnName, ' ', '') + ' = '''' BEGIN' + Char(13) END SET @UPSERT = @UPSERT + ISNULL(@INSERT, '') + Char(13) SET @UPSERT = @UPSERT + Char(9) + 'SELECT SCOPE_IDENTITY() As InsertedID' + Char(13) SET @UPSERT = @UPSERT + 'END' + Char(13) SET @UPSERT = @UPSERT + 'ELSE BEGIN' + Char(13) SET @UPSERT = @UPSERT + ISNULL(@UPDATE, '') + Char(13) SET @UPSERT = @UPSERT + 'END' + Char(13) + Char(13) SET @UPSERT = @UPSERT + 'SET NOCOUNT OFF' + Char(13) SET @UPSERT = @UPSERT + Char(13) -- _del -- delete proc completed already -- -------------------------------------------------- -- now either print the SP definitions or -- execute the statements to create the procs -- -------------------------------------------------- IF @PrintOrExecute <> 'Execute' BEGIN PRINT @LIST PRINT @SELECT PRINT @UPSERT PRINT @DELETE END ELSE BEGIN EXEC sp_Executesql @LIST EXEC sp_Executesql @SELECT EXEC sp_Executesql @UPSERT EXEC sp_Executesql @DELETE END END -- end @GenerateProcsFor = '' OR @GenerateProcsFor = @CurrentTable END
No comments:
Post a Comment