Tsql SQL Server字符串与Varchar连接(最大值)

Tsql SQL Server字符串与Varchar连接(最大值),tsql,sql-server-2012,Tsql,Sql Server 2012,我正试图通过将字符串连接到varchar max中来生成一个列名称列表,以便在动态查询中使用。在我遇到一个包含500多列的表之前,我一直使用的方法都很有效。在大表中,当我向列添加额外字符串以生成sql select脚本时,列列表被截断。 如果有人能告诉我为什么我的最后4个选择(如下)没有全部生成600行(当字段复制到新的查询窗口时,字段包含换行符),我将非常感谢。 Varchar(max)应该足够大,以产生我想要的结果。我只是不明白为什么会发生截断 --CREATE TABLE [dbo].[F

我正试图通过将字符串连接到varchar max中来生成一个列名称列表,以便在动态查询中使用。在我遇到一个包含500多列的表之前,我一直使用的方法都很有效。在大表中,当我向列添加额外字符串以生成sql select脚本时,列列表被截断。 如果有人能告诉我为什么我的最后4个选择(如下)没有全部生成600行(当字段复制到新的查询窗口时,字段包含换行符),我将非常感谢。 Varchar(max)应该足够大,以产生我想要的结果。我只是不明白为什么会发生截断

--CREATE TABLE [dbo].[Fact_NULLs_TEST]
--(
--My_really_quite_quite_quite_long_Column_name1 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name2 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name3 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name4 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name5 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name6 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name7 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name8 DECIMAL(18,2) NULL,
--My_really_quite_quite_quite_long_Column_name9 DECIMAL(18,2) NULL,
---- ......... etc up to My_really_quite_quite_quite_long_Column_name600
--)

DECLARE @Str AS VARCHAR(MAX)
DECLARE @Str2 AS VARCHAR(MAX)
DECLARE @Str3 AS VARCHAR(MAX)
DECLARE @Str4 AS VARCHAR(MAX)
SET @Str = ''
SET @Str2 = ''
SET @Str3 = ''
SET @Str4 = ''


SELECT 
    @Str = @Str + CAST(QUOTENAME(name) AS VARCHAR(MAX)) +  CAST(CHAR(13) AS VARCHAR(MAX))
FROM
MY_DB.sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')


SELECT 
    @Str2 = CAST(@Str2 AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) + CAST('my short text' AS VARCHAR(MAX)) + CAST(CHAR(13) AS VARCHAR(MAX))
FROM
MY_DB.sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')


SELECT 
    @Str3 = CAST(@Str3 AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) + CAST(' my long text my long text my long text my long text my long text ' AS VARCHAR(MAX)) + CAST(CHAR(13) AS VARCHAR(MAX))
FROM
MY_DB.sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')



SELECT 
    @Str4 = CAST(@Str4 AS VARCHAR(MAX)) + CAST('SUM(CASE WHEN ' AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) +  CAST(' IS NULL THEN 1 ELSE 0 END) AS ' AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) +  CAST(',' AS VARCHAR(MAX)) +  CAST(CHAR(13) AS VARCHAR(MAX))
FROM
MY_DB.sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')



SELECT @Str , LEN(@Str) --- 600 rows

SELECT @Str2, LEN(@Str2) --- 600 rows

SELECT @Str3 , LEN(@Str3) --- 378 rows ??????????????????

SELECT @Str4 , LEN(@Str4) --- 303 rows ??????????????????

发生这种情况的原因是,如果输入字符串超过其最大值(128个字符),quotename将返回null。 更多信息,请访问:

在您的代码中,也不需要在每个部分上添加强制转换,因为您连接的是一个声明的varchar(max)变量Str,您只需使用plus,甚至brakets添加所有内容,如下所示:

@Str = @Str + '['+name+']'+ CHAR(13)
不管怎样,似乎对单个可选对象返回的最大长度有一个未记录的限制,该对象使用SQLCMD和SQL Server Management Studio作为客户端执行SQL,因此,您可以通过简单的直接选择获得正确的文本,而不是将所有内容都放在一个字符串中,或者,如果您在程序中使用它,您需要打开一个游标并分别从结果集中获取每一行

我将使用带注释的结果来测试我使用的SQL

USE MY_DB

DECLARE @Str AS VARCHAR(MAX)
DECLARE @Str2 AS VARCHAR(MAX)
DECLARE @Str3 AS VARCHAR(MAX)
DECLARE @Str4 AS VARCHAR(MAX)
SET @Str = ''
SET @Str2 = ''
SET @Str3 = ''
SET @Str4 = ''


SELECT  
    @Str = @Str + '[' + name + ']'+ CHAR(13) 
FROM
sys.columns 
WHERE [object_id] = OBJECT_ID('[dbo].Fact_NULLs_TEST')

/*
SELECT 
    @Str2 = CAST(@Str2 AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) + CAST('my short text' AS VARCHAR(MAX)) + CAST(CHAR(13) AS VARCHAR(MAX))
FROM
sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')


SELECT 
    @Str3 = CAST(@Str3 AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) + CAST(' my long text my long text my long text my long text my long text ' AS VARCHAR(MAX)) + CAST(CHAR(13) AS VARCHAR(MAX))
FROM
sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')


*/
SELECT 
    --top 50 
    @Str4 = @Str4 + 
    ' SUM(CASE WHEN ' +'['+ sc.name +']' + ' IS NULL THEN 1 ELSE 0 END) AS ' +'[' + sc.name +'],' + CHAR(13)
FROM
sys.columns sc
WHERE [object_id] = OBJECT_ID('[dbo].Fact_NULLs_TEST')

SELECT @Str , LEN(@Str) --- 29892 chars
/*
SELECT @Str2, LEN(@Str2) --- 

SELECT @Str3 , LEN(@Str3) ---
*/
SELECT @Str4 , LEN(@Str4) --- 87384 chars BUT in case you use Microsoft SQL Server Management Studio and copy /paste into an editor this is coming out truncated

PRINT @Str4 --This is truncated as well if displayed from Messages tab within Microsoft SQL Server Management Studio or grabbed by using SQLCMD 
--with -o on a text file, i.e. SQLCMD -S dbserver -E -i c:\temp\test1.sql -o c:\temp\test1out.txt

SELECT 
    ' SUM(CASE WHEN ' +'['+ sc.name +']' + ' IS NULL THEN 1 ELSE 0 END) AS ' +'[' + sc.name +'],' 
FROM
sys.columns sc
WHERE [object_id] = OBJECT_ID('[dbo].Fact_NULLs_TEST') 
--This last select works fine either from Microsoft SQL Server Management Studio or by using SQLCMD

发生这种情况的原因是,如果输入字符串超过其最大值(128个字符),quotename将返回null。 更多信息,请访问:

在您的代码中,也不需要在每个部分上添加强制转换,因为您连接的是一个声明的varchar(max)变量Str,您只需使用plus,甚至brakets添加所有内容,如下所示:

@Str = @Str + '['+name+']'+ CHAR(13)
不管怎样,似乎对单个可选对象返回的最大长度有一个未记录的限制,该对象使用SQLCMD和SQL Server Management Studio作为客户端执行SQL,因此,您可以通过简单的直接选择获得正确的文本,而不是将所有内容都放在一个字符串中,或者,如果您在程序中使用它,您需要打开一个游标并分别从结果集中获取每一行

我将使用带注释的结果来测试我使用的SQL

USE MY_DB

DECLARE @Str AS VARCHAR(MAX)
DECLARE @Str2 AS VARCHAR(MAX)
DECLARE @Str3 AS VARCHAR(MAX)
DECLARE @Str4 AS VARCHAR(MAX)
SET @Str = ''
SET @Str2 = ''
SET @Str3 = ''
SET @Str4 = ''


SELECT  
    @Str = @Str + '[' + name + ']'+ CHAR(13) 
FROM
sys.columns 
WHERE [object_id] = OBJECT_ID('[dbo].Fact_NULLs_TEST')

/*
SELECT 
    @Str2 = CAST(@Str2 AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) + CAST('my short text' AS VARCHAR(MAX)) + CAST(CHAR(13) AS VARCHAR(MAX))
FROM
sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')


SELECT 
    @Str3 = CAST(@Str3 AS VARCHAR(MAX)) +  CAST(QUOTENAME(name) AS VARCHAR(MAX)) + CAST(' my long text my long text my long text my long text my long text ' AS VARCHAR(MAX)) + CAST(CHAR(13) AS VARCHAR(MAX))
FROM
sys.columns 
WHERE [object_id] = OBJECT_ID('[MY_DB].[dbo].Fact_NULLs_TEST')


*/
SELECT 
    --top 50 
    @Str4 = @Str4 + 
    ' SUM(CASE WHEN ' +'['+ sc.name +']' + ' IS NULL THEN 1 ELSE 0 END) AS ' +'[' + sc.name +'],' + CHAR(13)
FROM
sys.columns sc
WHERE [object_id] = OBJECT_ID('[dbo].Fact_NULLs_TEST')

SELECT @Str , LEN(@Str) --- 29892 chars
/*
SELECT @Str2, LEN(@Str2) --- 

SELECT @Str3 , LEN(@Str3) ---
*/
SELECT @Str4 , LEN(@Str4) --- 87384 chars BUT in case you use Microsoft SQL Server Management Studio and copy /paste into an editor this is coming out truncated

PRINT @Str4 --This is truncated as well if displayed from Messages tab within Microsoft SQL Server Management Studio or grabbed by using SQLCMD 
--with -o on a text file, i.e. SQLCMD -S dbserver -E -i c:\temp\test1.sql -o c:\temp\test1out.txt

SELECT 
    ' SUM(CASE WHEN ' +'['+ sc.name +']' + ' IS NULL THEN 1 ELSE 0 END) AS ' +'[' + sc.name +'],' 
FROM
sys.columns sc
WHERE [object_id] = OBJECT_ID('[dbo].Fact_NULLs_TEST') 
--This last select works fine either from Microsoft SQL Server Management Studio or by using SQLCMD

我已经从查询中删除了quotename,但仍然发生了截断?最后一个选择现在看起来是这样的,
code
select@Str4=@Str4+'SUM(当'+'['+name+']为NULL时,则为1 ELSE 0 END),作为'+name+','+CHAR(13)从MY_DB.sys.columns中[object\u id]=object\u id('[MY\u DB].[dbo].Fact\u NULLs\u TEST'))
code
非常感谢您的回答,非常感谢。我决定使用您最后的建议获取字段列表并遍历它们。我已经从查询中删除了quotename,但仍然发生了截断?最后的选择现在看起来是这样的,
code
select@Str4=@Str4+'SUM(当'+'['+name+']为空时,则为1,否则为0结束)作为'+name+','+CHAR(13)从MY_DB.sys.columns,其中[object_id]=object_id('[MY_DB].[dbo].Fact_NULLs_TEST')
code
非常感谢您的回答,非常感谢。我决定使用你最后的建议,获取字段列表并遍历它们是的,而不是我的设计。是的,不是我的设计。这就是我被赋予的工作。