use*_*104 8 sql-server stored-procedures sql-server-2008-r2 recovery sqlcmd
我制作了一个存储过程restoredatabase
,它返回代码来恢复数据库。输出脚本如下所示:
restore database [DB] from disk='F:\FULL1.bak' with norecovery
restore database [DB] from disk='F:\DIFF1.bak' with norecovery
restore log [DB] from disk='F:\log1.bak' with norecovery
restore log [DB] from disk='F:\log2.bak' with norecovery
...
restore log [DB] from disk='F:\logN.bak' with norecovery
restore database [DB] with recovery
Run Code Online (Sandbox Code Playgroud)
在整个 SP 中,这些行被添加到一个参数@sql varchar(max)
中,该参数最后以 打印print(@sql)
,如果用户指定了正确的标志,则以exec(@sql)
. 两者都完美地工作。但是,当像这样使用 sqlcmd 调用 SP 时:
set restoresql=exec restoredatabase @DB='Databasename', @Execute='y'
sqlcmd -h-1 -S SRV\T2 -U sa -P sa -d master -Q "%restoresql%" -o output.txt
Run Code Online (Sandbox Code Playgroud)
输出文件output.txt
将始终最多包含 4002 个字符。
我试过添加,-y 8000
但这没有帮助。如何获取输出文件以提供完整生成的脚本?
需要明确的是,问题实际上在于命令PRINT
而不是SQLCMD
实用程序。
我猜你的变量实际上是NVARCHAR(MAX)
,不是VARCHAR(MAX)
因为该命令使用/PRINT
限制为仅 4000 个字符。否则,它可以使用/输出最多 8000 个字符。要查看是否超过 4000 个字符,但不超过 8000 个字符,请运行以下命令:NCHAR
NVARCHAR
NVARCHAR
CHAR
VARCHAR
sqlcmd -Q "DECLARE @Yo VARCHAR(MAX) = REPLICATE(CONVERT(VARCHAR(MAX), '#'), 9000); PRINT @Yo;" -o out.txt
Run Code Online (Sandbox Code Playgroud)
如果需要打印超过 8000 个字符,则需要以最多 8000 个字符的块形式迭代变量(该命令一次PRINT
最多只能显示 8000CHAR
个字符)。VARCHAR
但是您不想简单地将其切成 8000 个字符的块,因为这可能正好位于不应拆分的内容的中间,例如单词/对象名称/数字等。因为该命令将始终包含PRINT
换行符字符结尾,最好打印每个 8000 个字符块的最后一个换行符。结果是,唯一被分割成多个显示行的行是那些在下一个换行符之前超过 8000 个字符的行,对此确实无能为力。
尝试使用以下过程代替您的print(@sql)
命令(仅供参考:您不需要像 for 一样使用@sql
括号)。请注意,查找字符串中的最后一个换行符需要创建一个函数,因为 T-SQL 中没有内置函数。您可以创建 T-SQL UDF 来执行此操作。您还可以使用 SQLCLR,在这种情况下您可以自己编写代码,或者直接获取SQL#库的免费版本(我是该库的作者)。PRINT
EXEC
LastIndexOf
SET ANSI_NULLS, QUOTED_IDENTIFIER ON;
IF (OBJECT_ID(N'dbo.Display') IS NOT NULL)
BEGIN
DROP PROCEDURE dbo.Display;
END;
GO
CREATE PROCEDURE dbo.Display
(
@TextToDisplay VARCHAR(MAX)
)
AS
SET NOCOUNT ON;
DECLARE @Length INT = LEN(@TextToDisplay),
@Buffer VARCHAR(8000),
@BufferLength INT,
@StartIndex INT = 1,
@LastNewlineIndex INT;
SET @TextToDisplay = REPLACE(@TextToDisplay, CHAR(13), ''); -- normalize
WHILE (1 = 1)
BEGIN
SET @Buffer = SUBSTRING(@TextToDisplay, @StartIndex, 8000);
SET @BufferLength = DATALENGTH(@Buffer);
IF (@BufferLength < 8000)
BEGIN
BREAK;
END;
SET @LastNewlineIndex =
SQL#.String_LastIndexOf(@Buffer, CHAR(10), @BufferLength, 1);
IF (@LastNewlineIndex > 0)
BEGIN
PRINT SUBSTRING(@Buffer, 1, (@LastNewlineIndex - 1));
SET @StartIndex += @LastNewlineIndex;
END;
ELSE
BEGIN
PRINT @Buffer;
SET @StartIndex += @BufferLength;
END;
END; -- WHILE (1 = 1)
-- Don't print empty line if final chunk was 8000 chars leaving final loop with 0
IF (DATALENGTH(@Buffer) > 0)
BEGIN
PRINT @Buffer;
END;
GO
Run Code Online (Sandbox Code Playgroud)
测试:
DECLARE @Test VARCHAR(MAX);
SET @Test = '';
SET @Test = @Test + '1' + REPLICATE('a', 7998) + '1';
SET @Test = @Test + '2' + REPLICATE('b', 7998) + '2';
SET @Test = @Test + '3' + REPLICATE('c', 7998) + '3';
SELECT @Test;
PRINT '=============================';
EXEC dbo.Display @Test;
PRINT '=============================';
----
SET @Test = '';
SET @Test = @Test + '1' + REPLICATE('a', 7998) + '1';
SET @Test = @Test + '2' + REPLICATE('b', 7998) + '2';
SET @Test = @Test + '3' + REPLICATE('c', 7000) + '3';
SELECT @Test;
PRINT '=============================';
EXEC dbo.Display @Test;
PRINT '=============================';
----
SET @Test = '';
SET @Test = @Test + '1.1' + REPLICATE('a', 7000) + '1.1' + CHAR(13) + CHAR(10);
SET @Test = @Test + '1.2' + REPLICATE('a', 400) + '1.2' + CHAR(13) + CHAR(10);
SET @Test = @Test + '1.3' + REPLICATE('a', 4000) + '1.3' + CHAR(13) + CHAR(10);
SET @Test = @Test + '2' + REPLICATE('b', 1798) + '2' + CHAR(13) + CHAR(10);
SET @Test = @Test + '3' + REPLICATE('c', 7000) + '3';
SELECT @Test;
PRINT '=============================';
EXEC dbo.Display @Test;
PRINT '=============================';
Run Code Online (Sandbox Code Playgroud)
笔记:
CHARINDEX
函数来查找每个下一个换行符,在这方面,它的功能几乎就像使用字符串拆分函数一样。这里需要的和在换行符上进行简单分割之间的区别在于,返回的任何超过 8000 个字符的元素仍然需要分割成不超过 8000 个字符的块。NVARCHAR(MAX)
而不是VARCHAR(MAX)
,使用我发布到 PasteBin 的代码:T-SQL Stored Proc to PRINT NVARCHAR(MAX) 值Util_Print
SQL# 库中有一个存储过程 ,它可以处理NVARCHAR(MAX)
上面显示的 T-SQL 代码并具有一些超出上述功能的功能,但它仅在完整(即付费)版本中可用,在免费版本中不可用。但此处显示的代码可以处理大多数情况。 归档时间: |
|
查看次数: |
14473 次 |
最近记录: |