Henry

曾经沧海难为水,除却巫山不是云,取次花丛懒回顾,半缘修道半缘君。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
CREATE PROCEDURE [dbo].[sp_generate_insert_script]
@tablename_mask VARCHAR(30) = NULL
AS
BEGIN

DECLARE @tablename VARCHAR(128)
DECLARE @tablename_max VARCHAR(128)
DECLARE @tableid INT
DECLARE @columncount NUMERIC(7, 0)
DECLARE @columncount_max NUMERIC(7, 0)
DECLARE @columnname VARCHAR(30)
DECLARE @columntype INT
DECLARE @string VARCHAR(30)
DECLARE @leftpart VARCHAR(8000) /* 8000 is the longest string SQLSrv7 can EXECUTE */
DECLARE @rightpart VARCHAR(8000) /* without having to resort to concatenation */
DECLARE @hasident INT

SET nocount ON

-- take ALL tables when no mask is given (!)
IF ( @tablename_mask IS NULL )
BEGIN
SELECT @tablename_mask = '%'
END

-- create table columninfo now, because it will be used several times

CREATE TABLE #columninfo
(
num NUMERIC(
7, 0) IDENTITY,
name
VARCHAR(30),
usertype
SMALLINT
)


SELECT name,
id
INTO #tablenames
FROM sysobjects
WHERE type IN ( 'U', 'S' )
AND name LIKE @tablename_mask

-- loop through the table #tablenames

SELECT @tablename_max = MAX(name),
@tablename = MIN(name)
FROM #tablenames

WHILE @tablename <= @tablename_max
BEGIN
SELECT @tableid = id
FROM #tablenames
WHERE name = @tablename

IF ( @@rowcount <> 0 )
BEGIN
-- Find out whether the table contains an identity column
SELECT @hasident = MAX(status & 0x80)
FROM syscolumns
WHERE id = @tableid

TRUNCATE TABLE #columninfo

INSERT INTO #columninfo ( name, usertype )
SELECT name,
type
FROM syscolumns C
WHERE id = @tableid
AND type <> 37 -- do not include timestamps

-- Fill @leftpart with the first part of the desired insert-statement, with the fieldnames

SELECT @leftpart = 'select ''insert into '
+ @tablename
SELECT @leftpart = @leftpart + '('

SELECT @columncount = MIN(num),
@columncount_max = MAX(num)
FROM #columninfo
WHILE @columncount <= @columncount_max
BEGIN
SELECT @columnname = name,
@columntype = usertype
FROM #columninfo
WHERE num = @columncount
IF ( @@rowcount <> 0 )
BEGIN
IF ( @columncount < @columncount_max )
BEGIN
SELECT @leftpart = @leftpart
+ @columnname + ','
END
ELSE
BEGIN
SELECT @leftpart = @leftpart
+ @columnname + ')'
END
END

SELECT @columncount = @columncount + 1
END

SELECT @leftpart = @leftpart + ' values('''

-- Now fill @rightpart with the statement to retrieve the values of the fields, correctly formatted

SELECT @columncount = MIN(num),
@columncount_max = MAX(num)
FROM #columninfo

SELECT @rightpart = ''

WHILE @columncount <= @columncount_max
BEGIN
SELECT @columnname = name,
@columntype = usertype
FROM #columninfo
WHERE num = @columncount

IF ( @@rowcount <> 0 )
BEGIN

IF @columntype IN ( 39, 47 ) /* char fields need quotes (except when entering NULL);
* use char(39) == ', easier readable than escaping
*/
BEGIN
SELECT @rightpart = @rightpart
+ '+'
SELECT @rightpart = @rightpart
+ 'ISNULL('
+ REPLICATE(CHAR(39), 4)
+ '+replace('
+ @columnname + ','
+ REPLICATE(CHAR(39), 4)
+ ','
+ REPLICATE(CHAR(39), 6)
+ ')+'
+ REPLICATE(CHAR(39), 4)
+ ',''NULL'')'
END

ELSE
IF @columntype = 35 /* TEXT fields cannot be RTRIM-ed and need quotes */
/* convert to VC 1000 to leave space for other fields */
BEGIN
SELECT @rightpart = @rightpart
+ '+'
SELECT @rightpart = @rightpart
+ 'ISNULL('
+ REPLICATE(CHAR(39), 4)
+ '+replace(convert(varchar(1000),'
+ @columnname
+ ')' + ','
+ REPLICATE(CHAR(39), 4)
+ ','
+ REPLICATE(CHAR(39), 6)
+ ')+'
+ REPLICATE(CHAR(39), 4)
+ ',''NULL'')'
END

ELSE
IF @columntype IN ( 58, 61, 111 ) /* datetime fields */
BEGIN
SELECT @rightpart = @rightpart + '+'
SELECT @rightpart = @rightpart + 'ISNULL(' + REPLICATE(CHAR(39), 4) + '+convert(varchar(20),' + @columnname + ')+' + REPLICATE(CHAR(39), 4) + ',''NULL'')'
END

ELSE /* numeric types */
BEGIN
SELECT @rightpart = @rightpart + '+'
SELECT @rightpart = @rightpart + 'ISNULL(convert(varchar(99),' + @columnname + '),''NULL'')'
END


IF ( @columncount < @columncount_max )
BEGIN
SELECT @rightpart = @rightpart
+ '+'','''
END

END
SELECT @columncount = @columncount + 1
END

END

SELECT @rightpart = @rightpart + '+'')''' + ' from '
+ @tablename

-- Order the select-statements by the first column so you have the same order for
--
different database (easy for comparisons between databases with different creation orders)
SELECT @rightpart = @rightpart + ' order by 1'

-- For tables which contain an identity column we turn identity_insert on
--
so we get exactly the same content

IF @hasident > 0
SELECT 'SET IDENTITY_INSERT ' + @tablename + ' ON'

EXEC ( @leftpart + @rightpart
)

IF @hasident > 0
SELECT 'SET IDENTITY_INSERT ' + @tablename + ' OFF'

SELECT @tablename = MIN(name)
FROM #tablenames
WHERE name > @tablename
END

END
posted on 2011-06-14 09:34  Henry.Lau  阅读(388)  评论(0编辑  收藏  举报