我 运行 脚本,它冻结了我,但 varchar(max) 和 nvarchar(max) -1 总是那些有抛出的。 max如何变成-1

I run the script and it freezes me but varchar(max) and nvarchar(max) -1 always the ones with throws. How max turns -1

ALTER FUNCTION [dbo].[get_logtable_script]
    (@table_name varchar(max)) 
RETURNS varchar(max) 
AS BEGIN
   declare @sql varchar(5000)
   declare @column_name varchar(max), @data_type varchar(max), @maxlength varchar(5)

   set @sql = 'create table TEST_Log.dbo.log_'+@table_name+' (logid [int] IDENTITY(1,1) NOT NULL,log_time date, log_tip varchar(10)' 

   declare itable cursor LOCAL for 
        SELECT
            COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH 
        FROM
            INFORMATION_SCHEMA.COLUMNS 
        WHERE
            TABLE_NAME = @table_name
        ORDER BY
            ORDINAL_POSITION

OPEN itable;
FETCH NEXT FROM itable INTO @column_name, @data_type, @maxlength

WHILE @@FETCH_STATUS = 0
BEGIN
    set SET @sql = @sql + ','+@column_name+' '+@data_type+case when isnull(@maxlength,'')= '' then '' else '('+ @maxlength + ')' end

    FETCH NEXT FROM itable INTO @column_name, @data_type, @maxlength
END

SET @sql = @sql + ')'   
CLOSE itable
DEALLOCATE itable

RETURN @sql
END

CHARACTER_MAXIMUM_LENGTH 对于 MAX-1 所以你的输出字符串是 varchar(-1) 这是不正确的,使用:

set @sql = @sql + ','+ quotename(@column_name) + ' ' + @data_type +
           case when @maxlength is null then '' else 
               '('+ case when @maxlength = -1 then 'max' else @maxlength end + ')' 
           end

请注意添加 quotename 来处理 reserved/spaced 列名称。 这种方法不适用于具有 scale/precision.

的类型

函数:

ALTER FUNCTION dbo.get_logtable_script
(
    @table_name SYSNAME
)
RETURNS NVARCHAR(MAX)
AS BEGIN

    DECLARE  
          @object_name SYSNAME  
        , @object_id INT  
        , @SQL NVARCHAR(MAX)  

    SELECT @object_name = name, @object_id = [object_id]  
    FROM sys.objects
    WHERE [object_id] = OBJECT_ID(@table_name, 'U')

SELECT @SQL = 'CREATE TABLE [TEST_Log].[dbo].[log_' + @object_name + '] (
      [logid] [INT] IDENTITY(1,1) NOT NULL
    , [log_time] [DATE]
    , [log_tip] [VARCHAR](10)
    ' + STUFF((  
    SELECT CHAR(13) + '    , [' + c.name + '] ' +   
        CASE WHEN c.is_computed = 1  
            THEN 'AS ' + OBJECT_DEFINITION(c.[object_id], c.column_id)  
            ELSE   
                CASE WHEN c.system_type_id != c.user_type_id   
                    THEN '[' + SCHEMA_NAME(tp.[schema_id]) + '].[' + tp.name + ']'   
                    ELSE '[' + UPPER(tp.name) + ']'   
                END  +   
                CASE   
                    WHEN tp.name IN ('varchar', 'char', 'varbinary', 'binary')  
                        THEN '(' + CASE WHEN c.max_length = -1   
                                        THEN 'MAX'   
                                        ELSE CAST(c.max_length AS VARCHAR(5))   
                                    END + ')'  
                    WHEN tp.name IN ('nvarchar', 'nchar')  
                        THEN '(' + CASE WHEN c.max_length = -1   
                                        THEN 'MAX'   
                                        ELSE CAST(c.max_length / 2 AS VARCHAR(5))   
                                    END + ')'  
                    WHEN tp.name IN ('datetime2', 'time2', 'datetimeoffset')   
                        THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')'  
                    WHEN tp.name = 'decimal'  
                        THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')'  
                    ELSE ''  
                END +  
                CASE WHEN c.collation_name IS NOT NULL AND c.system_type_id = c.user_type_id   
                    THEN ' COLLATE ' + c.collation_name  
                    ELSE ''  
                END +  
                CASE WHEN c.is_nullable = 1   
                    THEN ' NULL'  
                    ELSE ' NOT NULL'  
                END
        END  
    FROM sys.columns c WITH(NOLOCK)  
    JOIN sys.types tp WITH(NOLOCK) ON c.user_type_id = tp.user_type_id  
    LEFT JOIN sys.check_constraints cc WITH(NOLOCK)   
            ON c.[object_id] = cc.parent_object_id   
        AND cc.parent_column_id = c.column_id  
    WHERE c.[object_id] = @object_id  
    ORDER BY c.column_id  
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 5, '') + CHAR(13) + ');'  

    RETURN @SQL

END

测试:

USE [master]
GO

SELECT dbo.get_logtable_script('dbo.spt_monitor')

输出:

CREATE TABLE [TEST_Log].[dbo].[log_spt_monitor] (
      [logid] [INT] IDENTITY(1,1) NOT NULL
    , [log_time] [DATE]
    , [log_tip] [VARCHAR](10)
    , [lastrun] [DATETIME] NOT NULL
    , [cpu_busy] [INT] NOT NULL
    , [io_busy] [INT] NOT NULL
    , [idle] [INT] NOT NULL
    , [pack_received] [INT] NOT NULL
    , [pack_sent] [INT] NOT NULL
    , [connections] [INT] NOT NULL
    , [pack_errors] [INT] NOT NULL
    , [total_read] [INT] NOT NULL
    , [total_write] [INT] NOT NULL
    , [total_errors] [INT] NOT NULL
);

我的post:

How to Generate a CREATE TABLE Script For an Existing Table