根据提供的原始数据,生成测试数据表

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 功能:根据提问者提供的原始数据,生成测试数据表。                          *
 * 说明:1.单个/多个测试表一起生成。                                         *
 *       2.表类型:变量表/临时表/实体表,可控。                              *
 *       3.如无表名:T1...Tn;如无列名:c1...cn。                            *
 *       4.列填充:数据列不足填充NULL值;字段列不足以sql_variant填充cm...cn。*
 *       5.数据类型解析:自动解析最恰当的数据类型/长度。                     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 --> 多表测试:
cs '@var
id data
1 表变量

#tmp
id data
2 临时表

$tab
id,data
3 实体表'
go

/*
--> 测试数据: @var
declare @var table (id int,data varchar(6))
insert into @var
select 1,'表变量'
--> 测试数据: #tmp
if object_id('tempdb.dbo.#tmp') is not null drop table #tmp
create table #tmp (id int,data varchar(6))
insert into #tmp
select 2,'临时表'
--> 测试数据: [tab]
if object_id('[tab]') is not null drop table [tab]
create table [tab] (id int,data varchar(6))
insert into [tab]
select 3,'实体表'

select * from @var
select * from #tmp
select * from [tab]
*/

--> 无表名/无列名测试:
cs '@
id data
1 无表名

0#tmp
2 无列名

0$
3 双无'
go

/*
--> 测试数据: @T1
declare @T1 table (id int,data varchar(6))
insert into @T1
select 1,'无表名'
--> 测试数据: #tmp
if object_id('tempdb.dbo.#tmp') is not null drop table #tmp
create table #tmp (c1 int,c2 varchar(6))
insert into #tmp
select 2,'无列名'
--> 测试数据: [T3]
if object_id('[T3]') is not null drop table [T3]
create table [T3] (c1 int,c2 varchar(4))
insert into [T3]
select 3,'双无'

select * from @T1
select * from #tmp
select * from [T3]
*/

--> 保留原NULL值,字段数据分隔线忽略:
cs '@null
a    b
---- ----
11   null
null 22'
go
/*
--> 测试数据: @null
declare @null table (a int,b int)
insert into @null
select 11,null union all
select null,22

select * from @null
*/

--> 数据列不足,NULL值填充,数据左边对齐原则:
cs '@fill_null
a b c d
11 12 13
   21 22
      31'
go

/*
--> 测试数据: @fill_null
declare @fill_null table (a int,b int,c int,d sql_variant)
insert into @fill_null
select 11,12,13,null union all
select 21,22,null,null union all
select 31,null,null,null

select * from @fill_null
*/

--> 字段名不足,动态添加字段,以cm...cn命名:
cs '@add_column
a
11 12 13
   21 22
      31'
go

/*
--> 测试数据: @add_column
declare @add_column table (a int,c2 int,c3 int)
insert into @add_column
select 11,12,13 union all
select 21,22,null union all
select 31,null,null

select * from @add_column
*/

--> 占位符分号的作用——控制数据的位置,用NULL代替效果一样:
cs '@semicolon
a b c
11 12 13
;  22 23
;  ;  33'
go

/*
--> 测试数据: @semicolon
declare @semicolon table (a int,b int,c int)
insert into @semicolon
select 11,12,13 union all
select null,22,23 union all
select null,null,33

select * from @semicolon
*/

-->时间解析一:
cs '@time
id date boy
1 2001-1-1 Mark
2 20020101 John
3 23:15:39 Paul'
go

/*
--> 测试数据: @time
declare @time table (id int,date datetime,boy varchar(4))
insert into @time
select 1,'2001-1-1','Mark' union all
select 2,'20020101','John' union all
select 3,'23:15:39','Paul'

select * from @time
*/

-->时间解析二:
cs '@time
id date boy
1 2001-1-1 12:28:47 Mark
2 20020101 17:30:00 John
3 2003/1/1 23:15:39 Paul'
go

/*
--> 测试数据: @time
declare @time table (id int,date datetime,boy varchar(4))
insert into @time
select 1,'2001-1-1 12:28:47','Mark' union all
select 2,'20020101 17:30:00','John' union all
select 3,'2003/1/1 23:15:39','Paul'

select * from @time
*/

-->时间解析三——不支持:
cs '@time
id date boy
1 2001-1-1 12:28:47 Mark
2 20020101 John
3 2003/1/1 Paul'
go

/*
--> 测试数据: @time
declare @time table (id int,date datetime,boy varchar(8),c4 varchar(4))
insert into @time
select 1,'2001-1-1','12:28:47','Mark' union all
select 2,'20020101','John',null union all
select 3,'2003/1/1','Paul',null

select * from @time
*/

-->时间解析三——正确解析需要手工添加占位符:
cs '@time
id date boy
1 2001-1-1 12:28:47 Mark
2 20020101 ; John
3 2003/1/1 ; Paul'
go

/*
--> 测试数据: @time
declare @time table (id int,date datetime,boy varchar(4))
insert into @time
select 1,'2001-1-1 12:28:47','Mark' union all
select 2,'20020101','John' union all
select 3,'2003/1/1','Paul'

select * from @time
*/
*/


CREATE PROCEDURE cs @input VARCHAR(MAX)
AS 
    SET nocount ON
    IF PATINDEX('%[@#$]%', @input) = 0 
        RETURN
    SELECT  @input = REPLACE(@input, ' ', ' '), @input = LTRIM(RTRIM(@input))
    SELECT TOP 94
            code = IDENTITY( TINYINT,33,1), m = CAST(NULL AS VARCHAR(2)),
            w = CAST(NULL AS VARCHAR(1))
    INTO    #
    FROM    syscolumns
    SELECT  @input = REPLACE(@input COLLATE chinese_prc_cs_as_ks_ws,
                             NCHAR(code + 65248), CHAR(code))
    FROM    #
    TRUNCATE TABLE #
    INSERT  INTO #
            SELECT  CHAR(13), CHAR(10)
    INSERT  INTO #
            SELECT  CHAR(9), ','
    INSERT  INTO #
            SELECT  ' ', ','
    INSERT  INTO #
            SELECT  '|', ','
    INSERT  INTO #
            SELECT  '¦', ','
    INSERT  INTO #
            SELECT  '。', '.'
    INSERT  INTO #
            SELECT  '·', '.'
    INSERT  INTO #
            SELECT  CHAR(39), ''
    SELECT  @input = REPLACE(@input COLLATE chinese_prc_cs_as_ks_ws, m, w)
    FROM    #
    DROP TABLE #
    WHILE PATINDEX('%[^,][;]%', @input) > 0 
        SET @input = STUFF(@input, PATINDEX('%[^,][;]%', @input) + 1, 1, ',;')
    WHILE PATINDEX('%[;][^,]%', @input) > 0 
        SET @input = STUFF(@input, PATINDEX('%[;][^,]%', @input), 1, ';,')
    SET @input = REPLACE(@input, ';', 'null')
    WHILE CHARINDEX(',,', @input) > 0 
        SET @input = REPLACE(@input, ',,', ',')
    SET @input = REPLACE(@input, CHAR(10) + ',', CHAR(10))
    SET @input = REPLACE(@input, ',' + CHAR(10), CHAR(10))
    WHILE CHARINDEX(CHAR(10) + CHAR(10), @input) > 0 
        SET @input = REPLACE(@input, CHAR(10) + CHAR(10), CHAR(10))
    IF LEFT(@input, 1) = CHAR(10) 
        SET @input = RIGHT(@input, LEN(@input) - 1)
    IF RIGHT(@input, 1) <> CHAR(10) 
        SET @input = @input + CHAR(10)
    DECLARE @tab SYSNAME -- 表名:@=变量表;#=临时表;$=实体表
    DECLARE @tid TINYINT
    DECLARE @yes BIT
    DECLARE @cid SMALLINT
    DECLARE @col VARCHAR(1000)
    DECLARE @max SMALLINT
    DECLARE @type SYSNAME
    DECLARE @lenp SMALLINT
    DECLARE @lens SMALLINT
    DECLARE @sql VARCHAR(8000)
    DECLARE @tabs TABLE
        (
          id INT IDENTITY ,
          name SYSNAME
        )
    DECLARE @data TABLE
        (
          id INT IDENTITY ,
          data VARCHAR(8000)
        )
    DECLARE @temp TABLE
        (
          id INT ,
          temp VARCHAR(1000)
        )
    DECLARE @code TABLE
        (
          id INT ,
          code VARCHAR(8000)
        )
    IF CHARINDEX('$', @input) > 0 
        BEGIN
            SET @tab = SUBSTRING(@input, CHARINDEX('$', @input) + 1,
                                 CHARINDEX(CHAR(10), @input,
                                           CHARINDEX('$', @input))
                                 - CHARINDEX('$', @input) - 1)
            IF OBJECT_ID(@tab) IS NOT NULL 
                BEGIN
                    RAISERROR(N'数据库中已存在名为 ''%s'' 的对象。',16,1,@tab)
                    RETURN
                END
        END
    WHILE PATINDEX('%[@#$]%', @input) > 0 
        BEGIN
            SELECT  @tab = LEFT(@input, CHARINDEX(CHAR(10), @input) - 1),
                    @tid = ISNULL(@tid, 0) + 1, @yes = 1, @cid = 1,
                    @input = RIGHT(@input,
                                   LEN(@input) - CHARINDEX(CHAR(10), @input))
            IF LEFT(@tab, 1) = '0' 
                SELECT  @tab = STUFF(@tab, 1, 1, ''), @yes = 0
            IF LEN(@tab) = 1 
                SET @tab = @tab + 'T' + LTRIM(@tid)
            IF LEFT(@tab, 1) = '$' 
                SET @tab = QUOTENAME(STUFF(@tab, 1, 1, ''))
            INSERT  INTO @tabs
            VALUES  ( @tab )
            IF @yes = 0 
                SET @col = NULL
            ELSE 
                SELECT  @col = LEFT(@input, CHARINDEX(CHAR(10), @input) - 1)
                        + ',',
                        @input = RIGHT(@input,
                                       LEN(@input) - CHARINDEX(CHAR(10),
                                                              @input)),
                        @col = REPLACE(@col, ',', ':')
            WHILE CHARINDEX(CHAR(10), @input) > 0 
                BEGIN
                    INSERT  INTO @data
                            SELECT  LEFT(@input,
                                         CHARINDEX(CHAR(10), @input) - 1)
                    SET @input = RIGHT(@input,
                                       LEN(@input) - CHARINDEX(CHAR(10),
                                                              @input))
                    IF LEFT(@input, 1) IN ( '@', '#', '$' )
                        OR LEFT(@input, 2) IN ( '0@', '0#', '0$' ) 
                        BREAK
                END
            DELETE  FROM @data
            WHERE   PATINDEX('%[^,-]%', data) = 0
            SELECT  @max = MAX(LEN(data) - LEN(REPLACE(data, ',', '')))
            FROM    @data
            UPDATE  @data
            SET     data = data + REPLICATE(',null',
                                            @max - LEN(data)
                                            + LEN(REPLACE(data, ',', '')))
                    + ','
            SET @max = ISNULL(LEN(@col) - LEN(REPLACE(@col, ':', '')), 0)
            INSERT  INTO @code
                    SELECT  id, NULL
                    FROM    @data
                    ORDER BY id
            WHILE EXISTS ( SELECT   1
                           FROM     @data
                           WHERE    CHARINDEX(',', data) > 0 ) 
                BEGIN
                    INSERT  INTO @temp
                            SELECT  id,
                                    NULLIF(LEFT(data, CHARINDEX(',', data) - 1),
                                           'null')
                            FROM    @data
                            ORDER BY id
                    UPDATE  @data
                    SET     data = RIGHT(data,
                                         LEN(data) - CHARINDEX(',', data))
                    IF EXISTS ( SELECT  1
                                FROM    @temp a
                                        INNER JOIN @data b ON a.id = b.id
                                                              AND a.temp IS NOT NULL
                                                              AND LEFT(b.data,
                                                              4) NOT IN ( '',
                                                              'null' ) )
                        AND NOT EXISTS ( SELECT 1
                                         FROM   @temp a
                                                INNER JOIN @data b ON a.id = b.id
                                                              AND a.temp IS NOT NULL
                                                              AND LEFT(b.data,
                                                              4) NOT IN ( '',
                                                              'null' )
                                                              AND ISDATE(a.temp
                                                              + SPACE(1)
                                                              + LEFT(b.data,
                                                              CHARINDEX(',',
                                                              b.data) - 1)) = 0 ) 
                        BEGIN
                            UPDATE  a
                            SET     a.temp = a.temp + SPACE(1) + LEFT(b.data,
                                                              CHARINDEX(',',
                                                              b.data) - 1)
                            FROM    @temp a
                                    INNER JOIN @data b ON a.id = b.id
                            WHERE   a.temp IS NOT NULL
                                    AND LEFT(b.data,
                                             CHARINDEX(',', b.data) - 1) <> 'null'
                            UPDATE  @data
                            SET     data = RIGHT(data,
                                                 LEN(data) - CHARINDEX(',',
                                                              data))
                        END
                    IF NOT EXISTS ( SELECT  1
                                    FROM    @temp
                                    WHERE   temp IS NOT NULL ) 
                        SET @type = ' sql_variant'
                    ELSE 
                        IF NOT EXISTS ( SELECT  1
                                        FROM    @temp
                                        WHERE   temp IS NOT NULL
                                                AND ISNUMERIC(temp) = 0 ) 
                            BEGIN
                                IF EXISTS ( SELECT  1
                                            FROM    @temp
                                            WHERE   PATINDEX('%[Ee]%', temp) > 0 ) 
                                    SET @type = ' float'
                                ELSE 
                                    IF EXISTS ( SELECT  1
                                                FROM    @temp
                                                WHERE   CHARINDEX('.', temp) > 0 ) 
                                        BEGIN
                                            SELECT  @lenp = MAX(CHARINDEX('.',
                                                              CASE
                                                              WHEN LEFT(temp,
                                                              1) = '-'
                                                              THEN RIGHT(temp,
                                                              LEN(temp) - 1)
                                                              ELSE temp
                                                              END)) - 1,
                                                    @lens = MAX(CHARINDEX('.',
                                                              REVERSE(temp)))
                                                    - 1
                                            FROM    @temp
                                            WHERE   CHARINDEX('.', temp) > 0
                                            IF @lenp + @lens > @@max_precision 
                                                SET @type = ' float'
                                            ELSE 
                                                SET @type = ' numeric('
                                                    + LTRIM(@lenp + @lens)
                                                    + ',' + LTRIM(@lens) + ')'
                                        END
                                    ELSE 
                                        IF EXISTS ( SELECT  1
                                                    FROM    @temp
                                                    WHERE   LEN(temp) > 1
                                                            AND LEFT(temp, 1) = '0' ) 
                                            SELECT  @type = ' varchar('
                                                    + LTRIM(MAX(DATALENGTH(temp)))
                                                    + ')'
                                            FROM    @temp
                                            WHERE   temp IS NOT NULL
                                        ELSE 
                                            IF EXISTS ( SELECT
                                                              1
                                                        FROM  @temp
                                                        WHERE temp IS NOT NULL
                                                              AND LEN(temp) <> 8
                                                              OR ISDATE(temp) = 0 ) 
                                                BEGIN
                                                    SELECT  @lenp = ISNULL(MAX(LEN(temp)),
                                                              0)
                                                    FROM    @temp
                                                    WHERE   LEFT(temp, 1) <> '-'
                                                    SELECT  @lens = -ISNULL(MAX(LEN(temp)
                                                              - 1), 0)
                                                    FROM    @temp
                                                    WHERE   LEFT(temp, 1) = '-'
                                                    IF @lenp <= ABS(@lens) 
                                                        SELECT
                                                              @lenp = @lenp
                                                              + @lens,
                                                              @lens = @lenp
                                                              - @lens,
                                                              @lenp = @lenp
                                                              - @lens
                                                    IF ABS(@lenp) > 38 
                                                        SET @type = ' varchar('
                                                            + LTRIM(CASE
                                                              WHEN @lenp > 0
                                                              THEN @lenp
                                                              ELSE ABS(@lenp)
                                                              + 1
                                                              END) + ')'
                                                    ELSE 
                                                        IF EXISTS ( SELECT
                                                              1
                                                              FROM
                                                              @temp
                                                              WHERE
                                                              CAST(temp AS NUMERIC(38,
                                                              0)) NOT BETWEEN -9223372036854775808
                                                              AND
                                                              9223372036854775807 ) 
                                                            SET @type = ' numeric('
                                                              + LTRIM(ABS(@lenp))
                                                              + ',0)'
                                                        ELSE 
                                                            IF EXISTS ( SELECT
                                                              1
                                                              FROM
                                                              @temp
                                                              WHERE
                                                              CAST(temp AS NUMERIC(38,
                                                              0)) NOT BETWEEN -2147483648
                                                              AND
                                                              2147483647 ) 
                                                              SET @type = ' bigint'
                                                            ELSE 
                                                              SET @type = ' int'
                                                END
                                            ELSE 
                                                SET @type = ' datetime'
                            END
                        ELSE 
                            IF NOT EXISTS ( SELECT  1
                                            FROM    @temp
                                            WHERE   temp IS NOT NULL
                                                    AND ISDATE(temp) = 0 ) 
                                SET @type = ' datetime'
                            ELSE 
                                SELECT  @type = ' varchar('
                                        + LTRIM(MAX(DATALENGTH(temp))) + ')'
                                FROM    @temp
                                WHERE   temp IS NOT NULL
                    IF CHARINDEX(':', @col) > 0 
                        SET @col = STUFF(@col, CHARINDEX(':', @col), 1,
                                         @type + CASE WHEN @cid = @max THEN ''
                                                      ELSE ','
                                                 END)
                    ELSE 
                        SET @col = ISNULL(@col + ',', '') + 'c' + LTRIM(@cid)
                            + @type
                    UPDATE  a
                    SET     a.code = ISNULL(a.code + ',', 'select ')
                            + CASE WHEN SUBSTRING(@type, 2, 3) IN ( 'flo',
                                                              'num', 'big',
                                                              'int' )
                                   THEN ISNULL(b.temp, 'null')
                                   ELSE ISNULL(QUOTENAME(b.temp, CHAR(39)),
                                               'null')
                              END
                    FROM    @code a
                            INNER JOIN @temp b ON a.id = b.id
                    DELETE  FROM @temp
                    SET @cid = @cid + 1
                END
            IF @max > @cid - 1 
                BEGIN
                    SELECT  @col = STUFF(@col, LEN(@col), 1, ' sql_variant'),
                            @col = REPLACE(@col, ':', ' sql_variant,')
                    UPDATE  @code
                    SET     code = code + REPLICATE(',null', @max - @cid + 1)
                END
            SET @sql = NULL
            SELECT  @sql = ISNULL(@sql + ' union all' + CHAR(13) + CHAR(10),
                                  '') + code
            FROM    @code
            ORDER BY id
            PRINT '--> 测试数据: ' + @tab
            PRINT CASE LEFT(@tab, 1)
                    WHEN '@' THEN 'declare ' + @tab + ' table'
                    WHEN '#'
                    THEN 'if object_id(''tempdb.dbo.' + @tab
                         + ''') is not null drop table ' + @tab + CHAR(13)
                         + CHAR(10) + 'create table ' + @tab
                    ELSE 'if object_id(''' + @tab
                         + ''') is not null drop table ' + @tab + CHAR(13)
                         + CHAR(10) + 'create table ' + @tab
                  END + ' (' + @col + ')'
            PRINT 'insert into ' + @tab
            PRINT @sql
            DELETE  FROM @data
            DELETE  FROM @code
        END
    SET @sql = NULL
    SELECT  @sql = ISNULL(@sql + CHAR(13) + CHAR(10), CHAR(13) + CHAR(10))
            + 'select * from ' + name
    FROM    @tabs
    ORDER BY id
    PRINT @sql
    SET nocount OFF
go

原文地址:https://www.cnblogs.com/ToddLai/p/2287384.html