我 运行 脚本,它冻结了我,但 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:
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: