Varchar(最大)切削极限

时间:2016-01-14 21:21:09

标签: sql sql-server identity string-concatenation

我需要一个脚本来重新设置数据库中的每个标识列

我已经这样做了:

DECLARE @sqlreseed nvarchar(max)

SELECT 
    @sqlreseed = COALESCE(@sqlreseed + ' ', '') + 'set @id = (select isnull(max(' + cast(c.name as nvarchar(max)) +'), 0) + 1  from ' + CAST(t.name as nvarchar(max)) + ') DBCC CHECKIDENT (''' + cast(t.name as nvarchar(max)) +''', RESEED, @id); '
FROM 
    sys.schemas AS s
INNER JOIN 
    sys.tables AS t ON s.[schema_id] = t.[schema_id]
INNER JOIN 
    sys.identity_columns AS c on c.[object_id] = t.[object_id]

SET @sqlreseed = cast(cast('declare @id int ' as nvarchar(max)) + @sqlreseed as nvarchar(max))

EXEC(@sqlreseed)

但是我在列上遇到语法错误。

生成的脚本似乎很好

declare @id int set @id = (select isnull(max(SpecPositionID), 0) + 1  from SpecPosition_TS) DBCC CHECKIDENT ('SpecPosition_TS', RESEED, @id);  set @id = (select isnull(max(AuditId), 0) + 1  from TS_User_Audit) DBCC CHECKIDENT ('TS_User_Audit', RESEED, @id);  
每个表的

等等。每个checkident工作正常,但如果我用第一个查询运行它我已经发布了

  

BoxId'附近的语法不正确。

如果我执行len(@sqlreseed),我会收到70905。

我有很多桌子,但显然脚本正在削减。我在某个地方读到了问题,如果我连接字符串,我必须将它们全部转换为nvarchar(max),因为如果不是,它将被切割为8000但是我已经阅读了所有这些。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

试试这样:

SELECT SqlCommand + CHAR(10)--this concatenation without a column name is the magic to get "xml free" xml :-) Try this without the "+CHAR(10)"
FROM
(
    SELECT 0 AS inx, 'declare @id int;' AS SqlCommand
    UNION 
    SELECT
         ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) --Dummy Order
        ,'set @id = (select isnull(max(' + cast(c.name as nvarchar(max)) +'), 0) + 1  from ' + CAST(t.name as nvarchar(max)) + '); DBCC CHECKIDENT (''' + cast(t.name as nvarchar(max)) +''', RESEED, @id); '
    FROM 
        sys.schemas AS s
    INNER JOIN 
        sys.tables AS t ON s.[schema_id] = t.[schema_id]
    INNER JOIN 
        sys.identity_columns AS c on c.[object_id] = t.[object_id]
) AS tbl
ORDER BY tbl.inx 
FOR XML PATH('')

在XML Viewer中,您(几乎)无限制。右键单击您的查询并选择选项,勾选网格并将XML(最后一点)设置为"无限制"。

Btw:与SELECT @var=@var+...的字符串连接非常慢。上面显示的方式应该会更好......

答案 1 :(得分:0)

正如@Blorgbeard在评论中发布的那样,解决方案是在生成的字符串的列名中使用[]

可能有一个包含一些特殊名称或字符的列名。

我还在所有连接中使用强制转换为nvarchar(max),以确保限制不限于8000,因为我已阅读

V 2.0(完全正常)就是这个。

declare @sqlreseed nvarchar(max)
SELECT @sqlreseed = COALESCE(cast(@sqlreseed as nvarchar(max)) + ' ', '') + 'set @id = (select isnull(max([' + cast(c.name as nvarchar(max)) +']), 0) + 1  from [' + CAST(s.name as nvarchar(max)) + '].[' + CAST(t.name as nvarchar(max)) + ']) DBCC CHECKIDENT (''' + cast(t.name as nvarchar(max)) +''', RESEED, @id); '
FROM sys.schemas AS s
INNER JOIN sys.tables AS t ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.identity_columns AS c on c.[object_id] = t.[object_id]
SET @sqlreseed = cast(cast('declare @id int ' as nvarchar(max)) + @sqlreseed as nvarchar(max))
exec(@sqlreseed)