データベースを復元するためのコードを返すストアドプロシージャ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
_
SPを介して、行はパラメーター@sql varchar(max)
に追加され、最後にprint(@sql)
を使用して出力されます。ユーザーが正しいフラグを指定した場合は、exec(@sql)
。どちらも完全に機能します。ただし、SPをsqlcmdで次のように呼び出すと、
_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
_
出力ファイル_output.txt
_は、常に最大4002文字です。
_-y 8000
_を追加しようとしましたが、それは役に立ちません。出力ファイルを取得して、生成された完全なスクリプトを取得するにはどうすればよいですか?
明確にするために、問題は実際にはPRINT
コマンドではなく、SQLCMD
ユーティリティにあります。
PRINT
コマンドは、NCHAR
/NVARCHAR
を使用して4000文字に制限されているため、変数は実際にはNVARCHAR(MAX)
ではなくVARCHAR(MAX)
であると思います。それ以外の場合は、NVARCHAR
/CHAR
を使用して最大8000文字を出力できます。 VARCHAR
が4000文字を超え、8000文字を超えないことを確認するには、次のコマンドを実行します。
sqlcmd -Q "DECLARE @Yo VARCHAR(MAX) = REPLICATE(CONVERT(VARCHAR(MAX), '#'), 9000); PRINT @Yo;" -o out.txt
8000文字を超える印刷が必要な場合は、最大8000文字のチャンクで変数を反復処理する必要があります(PRINT
コマンドは、一度に最大8000個のCHAR
/VARCHAR
文字のみを表示します)。ただし、単語/オブジェクト名/番号など、分割してはいけないものの真ん中にある可能性があるため、単純に8000文字のチャンクに分割したくない場合があります。PRINT
コマンドには常に最後の改行文字。各8000文字のチャンクの最後の改行文字までを印刷するのが最適です。その結果、複数の表示された行に分割される唯一の行は、次の改行文字の前に8000文字を超える行であり、それについて実際にできることは何もありません。
print(@sql)
コマンドの代わりに次のプロシージャを試してください(FYI:PRINT
の場合のようにEXEC
の場合、@sql
を括弧で囲む必要はありません)。文字列内の最後の改行文字を見つけるには、T-SQLに組み込まれていないLastIndexOf
関数を作成する必要があることに注意してください。これを行うためのT-SQL UDFを作成できます。 SQLCLRを使用することもできます。その場合は、自分でコーディングするか、単純に SQL# ライブラリの無料版(私が作成者です)を入手できます。
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
テスト:
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 '=============================';
ノート:
CHARINDEX
関数を使用して次の各改行を探すためにできます。この点で、文字列分割関数を使用するのとほとんど同じように機能します。 。ここで必要なことと改行で単純な分割を行うことの違いは、8000文字を超える返される要素は、8000文字以下のチャンクに分割する必要があるということです。NVARCHAR(MAX)
の代わりにVARCHAR(MAX)
を処理するには、Pastebinに投稿したコードを使用します。 T-SQL Stored Proc to PRINT NVARCHAR(MAX)valuesUtil_Print
がSQL#ライブラリにあり、NVARCHAR(MAX)
を処理し、上記のT-SQLコード以外の機能を備えていますが、フル(つまり、有償)でのみ使用できます。無料版ではなく、バージョン。ただし、ここに示すコードはほとんどの場合を処理します。