Quando executamos o seguinte comando:
DBCC SHRINKFILE('MyDB_log', 1)
Obtemos os seguintes resultados no SSMS:
DBID | Field | CurrentSize | MinimumSize | UsedPages | Estimated Pages
-----|-------|-------------|-------------|-----------|----------------
11 | 2 | 128 | 128 | 128 | 128
A questão:
Como podemos criar uma consulta que gere esses resultados em um arquivo de texto, sem usar a janela de saída do SSMS.
Eu tentei isso:
CREATE TABLE #x
(
[DBID] int,
FileID int,
CurrentSize int,
MinimumSize int,
UsedPages int,
EstimatedPages int
)
INSERT #x
EXEC('DBCC SHRINKFILE(''MyDB_log'', 1)')
SELECT *
FROM #x
DROP TABLE #x
Mas recebo o seguinte erro:
Msg 8920, Level 16, State 2, Line 1
Cannot perform a shrinkfile operation inside a user transaction. Terminate the transaction and reissue the statement.
Eu também tentei o seguinte:
DECLARE @Statement AS VARCHAR(2000);
SET @Statement = 'bcp "DBCC SHRINKFILE(''MyDB_log'', 1)" queryout C:\Test.txt -c -UDBAdmin -P1234 -S192.168.123.123';
exec xp_cmdshell @Statement
Eu recebo:
Error = [Microsoft][SQL Native Client]BCP host-files must contain at least one column
A maneira mais fácil de ver é um arquivo em lote usando sqlcmd:
O operador de redirecionamento anexa dados no final do arquivo.
O parâmetro -Q foi usado para fechar a sessão sqlcmd imediatamente.
Você pode enviar os resultados da consulta para o arquivo pressionando Ctrl+Shift+F se estiver visualizando uma consulta única.
Se você está procurando algo que possa automatizar, pode agrupar a consulta no Powershell ou em outra linguagem de script e fazer com que grave o arquivo.
Existem duas opções bastante simples: usar um servidor vinculado ou SQLCLR.
servidor vinculado
Esta opção requer três coisas:
que a
'remote proc transaction promotion'
propriedade do Linked Server seja definida comofalse
, o que impede que o SQL Server tente usar o MSDTC para vincular as ações locais e remotas em uma única transação.que a
'rpc out'
propriedade do Linked Server paratrue
que o conjunto de resultados retornado porDBCC
possa ser passado de volta para o contexto local.e que você usa o Linked Server via
EXEC('DBCC...') AT [LinkedServerName];
Para obter um exemplo prático dessa abordagem, consulte minha resposta (também aqui no DBA.SE) para:
Como posso salvar os resultados do DBCC SHRINKFILE em uma tabela?
SQLCLRGenericName
Usando uma conexão regular/externa (ou seja, não a conexão de contexto) que tem a
Enlist
palavra-chave da string de conexão definida comofalse
, você pode criar um SQLCLR Stored Procedure ou Scalar Function / UDF. Assim como com o Linked Server'remote proc transaction promotion'
desativado, a nova conexão comEnlist = false;
não tentará vincular as transações locais e remotas.Embora um UDF se preste mais a ser usado em operações baseadas em conjunto, a abordagem mais simples (acredito, mas não testei) seria criar um procedimento armazenado no qual você passa
SqlCommand.ExecuteReader()
(onde oSqlCommand
objeto é a chamada paraDBCC
) paraSqlContext.Pipe.Send()
.