Eu fiz um procedimento armazenado restoredatabase
que retorna código para restaurar um banco de dados. O script de saída fica assim:
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
Ao longo do SP, as linhas são adicionadas a um parâmetro @sql varchar(max)
que, ao final, é impresso com print(@sql)
, e se o usuário especificou o sinalizador correto, é executado com exec(@sql)
. Ambos funcionam perfeitamente. No entanto, ao chamar o SP com sqlcmd assim:
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
O arquivo de saída output.txt
sempre terá no máximo 4002 caracteres.
Eu tentei adicionar, -y 8000
mas isso não ajuda. Como posso obter o arquivo de saída para me fornecer o script gerado completo?
Para ser claro, o problema é realmente com o
PRINT
comando e não com oSQLCMD
utilitário.Eu estou supondo que sua variável é realmente
NVARCHAR(MAX)
, nãoVARCHAR(MAX)
desde que oPRINT
comando é limitado a apenas 4000 caracteres usandoNCHAR
/NVARCHAR
. Caso contrário, pode produzir até 8000 caracteres usandoNVARCHAR
/CHAR
. Para verVARCHAR
se vai além de 4.000 caracteres, mas não além de 8.000, execute o seguinte:Se você precisar de mais de 8.000 caracteres impressos, precisará iterar a variável em blocos de até 8.000 caracteres (o
PRINT
comando exibirá apenas até 8.000CHAR
/VARCHAR
caracteres por vez). Mas você não quer simplesmente cortá-lo em pedaços de 8.000 caracteres, pois isso pode estar bem no meio de algo que não deve ser dividido, como uma palavra / nome de objeto / número, etc. Como oPRINT
comando sempre incluirá uma nova linha caractere no final, é melhor imprimir até o último caractere de nova linha de cada bloco de 8.000 caracteres. O resultado é que as únicas linhas a serem divididas em várias linhas exibidas são aquelas com mais de 8.000 caracteres antes do próximo caractere de nova linha, e não há realmente nada que possa ser feito sobre isso.Tente o seguinte proc no lugar do seu
print(@sql)
comando (FYI: você não precisa de parênteses como faz para@sql
) . Observe que encontrar o último caractere de nova linha em uma string requer a criação de uma função, pois uma não é incorporada ao T-SQL. Você pode criar um UDF T-SQL para fazer isso. Você também pode usar o SQLCLR, caso em que você mesmo pode codificar ou simplesmente obter a versão gratuita da biblioteca SQL# (da qual sou o autor).PRINT
EXEC
LastIndexOf
Testes:
NOTAS:
CHARINDEX
função interna para procurar cada nova linha seguinte e, a esse respeito, funcionaria quase como usar uma função de divisão de string. A diferença entre o que é necessário aqui e fazer uma divisão simples em novas linhas é que qualquer elemento retornado com mais de 8.000 caracteres ainda precisará ser dividido em blocos de até 8.000 caracteres.NVARCHAR(MAX)
em vez deVARCHAR(MAX)
, use o código que postei no PasteBin: T-SQL Stored Proc to PRINT NVARCHAR(MAX) valuesUtil_Print
, na biblioteca SQL# que manipulaNVARCHAR(MAX)
e possui algumas funcionalidades além do código T-SQL mostrado acima, mas que só está disponível na versão completa (ou seja, paga), não na versão gratuita. Mas o código mostrado aqui lidará com a maioria dos casos.