Recursos ocultos do SQL Server

215

Quais são alguns recursos ocultos do SQL Server ?

Por exemplo, procedimentos armazenados de sistema não documentado, truques para fazer coisas que são muito úteis, mas não documentadas o suficiente?


Respostas

Obrigado a todos por todas as ótimas respostas!

Procedimentos armazenados

  • sp_msforeachtable: executa um comando com '?' substituído por cada nome de tabela (v6.5 e superior)
  • sp_msforeachdb: executa um comando com '?' substituído por cada nome de banco de dados (v7 e superior)
  • sp_who2: assim como sp_who, mas com muito mais informações para solucionar problemas de blocos (v7 e superior)
  • sp_helptext: se você deseja o código de um procedimento armazenado, visualize & UDF
  • sp_tables: retorna uma lista de todas as tabelas e visualizações do banco de dados no escopo.
  • sp_stored_procedures: retorna uma lista de todos os procedimentos armazenados
  • xp_sscanf: lê dados da cadeia de caracteres nos locais dos argumentos especificados por cada argumento de formato.
  • xp_fixeddrives:: Encontre a unidade fixa com o maior espaço livre
  • sp_help: se você deseja conhecer a estrutura da tabela, índices e restrições de uma tabela. Também visualizações e UDFs. O atalho é Alt + F1

Trechos

  • Retornando linhas em ordem aleatória
  • Todos os objetos de usuário do banco de dados por data da última modificação
  • Somente data de retorno
  • Encontre registros cuja data esteja em algum lugar da semana atual.
  • Encontre registros cuja data ocorreu na semana passada.
  • Retorna a data para o início da semana atual.
  • Retorna a data do início da semana passada.
  • Veja o texto de um procedimento que foi implantado em um servidor
  • Descartar todas as conexões com o banco de dados
  • Soma de verificação da tabela
  • Soma de verificação de linha
  • Solte todos os procedimentos em um banco de dados
  • Mapeie novamente os IDs de login corretamente após a restauração
  • Chamar procedimentos armazenados de uma instrução INSERT
  • Localizar procedimentos por palavra-chave
  • Solte todos os procedimentos em um banco de dados
  • Consulte o log de transações para um banco de dados programaticamente.

Funções

  • HashBytes ()
  • EncryptByKey
  • Comando PIVOT

Diversos

  • Extras da String de Conexão
  • TableDiff.exe
  • Disparadores para eventos de logon (novos no Service Pack 2)
  • Aumentando o desempenho com colunas computadas persistentes (pcc).
  • Configuração DEFAULT_SCHEMA em sys.database_principles
  • Parametrização Forçada
  • Formato de armazenamento vardecimal
  • Descobrir as consultas mais populares em segundos
  • Bancos de dados compartilhados escaláveis
  • Recurso Tabela / Filtro de Procedimento Armazenado no SQL Management Studio
  • Sinalizadores de rastreamento
  • Número após a GOrepetição do lote
  • Segurança usando esquemas
  • Criptografia usando funções de criptografia integradas, visualizações e tabelas básicas com gatilhos
Sklivvz
fonte
4
Se conhecido, seria bom incluir as versões aplicáveis ​​em cada resposta. (2000 ou superior, 2005, 2000, apenas, etc.)
bw
Há muita bondade nessa questão. Por favor, não o apague! :-)
Sklivvz

Respostas:

91

No Management Studio, você pode colocar um número após um marcador de fim de lote do GO para fazer com que o lote seja repetido esse número de vezes:

PRINT 'X'
GO 10

Irá imprimir 'X' 10 vezes. Isso pode salvá-lo de copiar / colar tediosamente ao fazer coisas repetitivas.

GilM
fonte
70

Muitos desenvolvedores do SQL Server ainda parecem não conhecer a cláusula OUTPUT (SQL Server 2005 e mais recente) na instrução DELETE, INSERT e UPDATE.

Pode ser extremamente útil saber quais linhas foram INSERTed, UPDATEd ou DELETEd, e a cláusula OUTPUT permite fazer isso com muita facilidade - permite acesso às tabelas "virtuais" chamadas insertede deleted(como nos gatilhos):

DELETE FROM (table)
OUTPUT deleted.ID, deleted.Description
WHERE (condition)

Se você estiver inserindo valores em uma tabela que possui um campo de chave primária INT IDENTITY, com a cláusula OUTPUT, é possível obter o novo ID inserido imediatamente:

INSERT INTO MyTable(Field1, Field2)
OUTPUT inserted.ID
VALUES (Value1, Value2)

E se você estiver atualizando, pode ser extremamente útil saber o que mudou - nesse caso, insertedrepresenta os novos valores (após o UPDATE), enquanto deletedse refere aos valores antigos antes do UPDATE:

UPDATE (table)
SET field1 = value1, field2 = value2
OUTPUT inserted.ID, deleted.field1, inserted.field1
WHERE (condition)

Se muitas informações forem retornadas, a saída de OUTPUT também poderá ser redirecionada para uma tabela temporária ou uma variável de tabela ( OUTPUT INTO @myInfoTable).

Extremamente útil - e muito pouco conhecido!

Marc

marc_s
fonte
52

sp_msforeachtable: Executa um comando com '?' substituído por cada nome de tabela. por exemplo

exec sp_msforeachtable "dbcc dbreindex('?')"

Você pode emitir até 3 comandos para cada tabela

exec sp_msforeachtable
    @Command1 = 'print ''reindexing table ?''',
    @Command2 = 'dbcc dbreindex(''?'')',
    @Command3 = 'select count (*) [?] from ?'

Além disso, sp_MSforeachdb

Mitch Wheat
fonte
2
Você pode obter o nome da tabela na consulta usando aspas simples ao redor do ponto de interrogação. sp_msforeachtable "selecione contagem (*), '?' como tabenm de? "
Jody
51

Extras da String de conexão:

MultipleActiveResultSets = true;

Isso faz com que o ADO.Net 2.0 e superior leia vários conjuntos de resultados somente para encaminhamento e somente leitura em uma única conexão com o banco de dados, o que pode melhorar o desempenho se você estiver lendo muito. Você pode ativá-lo mesmo se estiver misturando tipos de consulta.

Nome do aplicativo = MyProgramName

Agora, quando você desejar ver uma lista de conexões ativas consultando a tabela sysprocesses, o nome do seu programa aparecerá na coluna program_name em vez de em ".Net SqlClient Data Provider"

Chris Wenham
fonte
7
Tornei o nome do aplicativo um requisito na minha empresa. Todo novo aplicativo deve ter um nome exclusivo. Facilita o rastreamento de qual aplicativo bloqueou / quebrou algo.
214 Neil N
2
Nome do aplicativo também está disponível como um filtro no criador de perfil. Ajuda muito se você deseja ver apenas suas consultas e não as consultas de seus colegas de trabalho.
Mathias F
33

TableDiff.exe

  • A ferramenta Table Difference permite descobrir e reconciliar diferenças entre uma tabela de origem e destino ou uma exibição. O utilitário Tablediff pode relatar diferenças no esquema e nos dados. O recurso mais popular do tablediff é o fato de ele poder gerar um script que você pode executar no destino que reconciliará as diferenças entre as tabelas.

Ligação

Sklivvz
fonte
31

Uma técnica TSQL menos conhecida para retornar linhas em ordem aleatória:

-- Return rows in a random order
SELECT 
    SomeColumn 
FROM 
    SomeTable
ORDER BY 
    CHECKSUM(NEWID())
Mitch Wheat
fonte
6
Ótimo para conjuntos de resultados pequenos. Eu não iria utilizá-lo em uma tabela com mais de 10.000 linhas a menos que você tem tempo de sobra
John Sheehan
Eu usei em mesas muito maiores que isso, e não foi muito lento.
Mitch Wheat
Qual é o objetivo do CHECKSUM ()? Você pode solicitar apenas NEWID ().
Jonas Lincoln
6
Eu já vi resultados decentes em 100.000.000 (100 mil) linhas, sem CHECKSUM (). Além disso, tenho que perguntar também, por que não apenas ENCOMENDAR POR NEWID?
Troy DeMonbreun 14/10/08
5
@GateKiller: revirei sua edição, porque o Checksum () não é um erro; reduz o tamanho da coluna de classificação.
Mitch Wheat
30

No Management Studio, você pode obter rapidamente uma lista de colunas delimitada por vírgulas para uma tabela:

  1. No Pesquisador de Objetos, expanda os nós em uma determinada tabela (para ver pastas para Colunas, Chaves, Restrições, Disparadores etc.)
  2. Aponte para a pasta Colunas e arraste para uma consulta.

Isso é útil quando você não deseja usar o formato hediondo retornado clicando com o botão direito do mouse na tabela e escolhendo Script Table As ..., depois Insert To ... Esse truque funciona com as outras pastas em que ele lhe dará uma lista delimitada por vírgula de nomes contidos na pasta.

Thomas
fonte
23

Construtores de linha

Você pode inserir várias linhas de dados com uma única instrução de inserção.

INSERT INTO Colors (id, Color)
VALUES (1, 'Red'),
       (2, 'Blue'),
       (3, 'Green'),
       (4, 'Yellow')
Rob Boek
fonte
Eu votei a favor, mas tentei no MSSQL 2005, e ele não funciona. 2008 apenas?
Richardtallent
11
Sim, é um novo recurso de 2008.
Rob Boek
2
Esse foi um recurso que eu perdi quando vim do DB2 para o SQL Server. No DB2, houve uma melhoria significativa da velocidade ao usar isso em vez de instruções de inserção individuais
Nathan Koop
22

Se você deseja conhecer a estrutura da tabela, índices e restrições:

sp_help 'TableName'
Eduardo Molteni
fonte
Combine esta dica com sua tecla de atalho! Primeiro destacar um tablename e depois bateu ALT + F1
Michael J Swart
22

HashBytes () para retornar o hash MD2, MD4, MD5, SHA ou SHA1 de sua entrada.

Joel Coehoorn
fonte
Agradável! O link correto é msdn.microsoft.com/en-us/library/ms174415(SQL.90).aspx (versão de 2005)
Sklivvz
Você está certo, essa foi a versão de 2008 dos documentos, embora as páginas sejam praticamente idênticas. Corrigido agora.
Joel Coehoorn
20

Descobrir as consultas mais populares

  • Com sys.dm_exec_query_stats, você pode descobrir muitas combinações de análises de consulta por uma única consulta.

Link com o commnad

select * from sys.dm_exec_query_stats 
order by execution_count desc
Sklivvz
fonte
16

EXCETO e INTERSECT

Em vez de escrever junções e subconsultas elaboradas, essas duas palavras-chave são uma maneira mais rápida e legível de expressar a intenção da sua consulta ao comparar dois resultados da consulta. Novo no SQL Server 2005, eles complementam fortemente o UNION, que já existe na linguagem TSQL há anos.

Os conceitos de EXCEPT, INTERSECT e UNION são fundamentais na teoria dos conjuntos, que serve como base e fundamento da modelagem relacional usada por todos os RDBMS modernos. Agora, os resultados do tipo de diagrama de Venn podem ser gerados de maneira mais intuitiva e fácil usando o TSQL.

Ray Vega
fonte
16

Eu sei que não está exatamente oculto, mas poucas pessoas sabem sobre o comando PIVOT . Eu era capaz de alterar um procedimento armazenado que usava cursores e levava 2 minutos para executar em um rápido código de 6 segundos que era um décimo do número de linhas!

Ronald Wildenberg
fonte
16

útil ao restaurar um banco de dados para fins de teste ou o que for. Re-mapeia os IDs de login corretamente:

EXEC sp_change_users_login 'Auto_Fix', 'Mary', NULL, 'B3r12-36'
Kolten
fonte
Este procedimento não funcionou antes e tive que alterar a propriedade dos objetos para um usuário temporário, largar o usuário original, adicionar novamente o original e atribuir a propriedade novamente. Ugh ...
StingyJack
15

Solte todas as conexões com o banco de dados:

Use Master
Go

Declare @dbname sysname

Set @dbname = 'name of database you want to drop connections from'

Declare @spid int
Select @spid = min(spid) from master.dbo.sysprocesses
where dbid = db_id(@dbname)
While @spid Is Not Null
Begin
        Execute ('Kill ' + @spid)
        Select @spid = min(spid) from master.dbo.sysprocesses
        where dbid = db_id(@dbname) and spid > @spid
End
GateKiller
fonte
Existe um parâmetro de banco de dados de uma linha ou gota que faça isso por mim? Percebo que se você tentar 'excluir banco de dados' através da interface do usuário, há uma caixa de seleção para 'fechar conexões existentes', o que implica que é um parâmetro booleano.
DevinB 16/04/09
1
Na verdade, acabei de encontrar uma solução de duas linhas. ALTER DATABASE [@ DATABASE_NAME @] SET READ_ONLY COM ROLLBACK IMEDIATA --este desconecta todos os usuários ALTER DATABASE [@ DATABASE_NAME @] SET READ_WRITE COM ROLLBACK IMEDIATA DROP DATABASE [@ DATABASE_NAME @]
DevinB
1
ALTER DATABASE MyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATEimpedirá que novas conexões ocorram também.
ErikE
15

Soma de verificação da tabela

Select CheckSum_Agg(Binary_CheckSum(*)) From Table With (NOLOCK)

Soma de verificação de linha

Select CheckSum_Agg(Binary_CheckSum(*)) From Table With (NOLOCK) Where Column = Value
GateKiller
fonte
2
Isso permite que você produza uma soma de verificação para todos os dados na tabela. É uma maneira simples e rápida de verificar se duas linhas ou duas tabelas são iguais.
GateKiller 23/09/08
15

Não tenho certeza se esse é um recurso oculto ou não, mas me deparei com isso, e achei útil em muitas ocasiões. Você pode concatonar um conjunto de um campo em uma única instrução de seleção, em vez de usar um cursor e percorrer a instrução de seleção.

Exemplo:

DECLARE @nvcConcatonated nvarchar(max)
SET @nvcConcatonated = ''

SELECT @nvcConcatonated = @nvcConcatonated + C.CompanyName + ', '
FROM tblCompany C
WHERE C.CompanyID IN (1,2,3)

SELECT @nvcConcatonated

Resultados:

Acme, Microsoft, Apple,
Sheki
fonte
2
você também pode usar COALESCE () para fazer a mesma coisa sem a necessidade de inicializar a variável. SELECT @nvcConcatonated = COALESCE (@nvcConcatonated + ',', '') + CAST (C.CompanyName como VARCHAR (255)) FROM ...
Christopher Klein
Isso também funciona em uma declaração de atualização. Às vezes, útil para fazer coisas como concatenar uma lista de IDs que foram atualizadas.
EBarr 14/09/11
14

Se você deseja o código de um procedimento armazenado, pode:

sp_helptext 'ProcedureName'

(não tenho certeza se é um recurso oculto, mas eu o uso o tempo todo)

Eduardo Molteni
fonte
Não sei por que, mas a saída sp_helptext é um pouco boba em qualquer linha excessivamente longa no original. Ao criar scripts para Sprocs, isso não acontece, então talvez exista outro mecanismo de exportação mais robusto? sp_helptext 'MyView' também é útil.
217 Kristen Kristen
Não sei bem o que você quer dizer. Para mim, o código SPs são outputed com o mesmo formato que tenho script-los no arquivo original (com todos os CRs, etc)
Eduardo Molteni
Não me lembro dos detalhes exatos , mas isso tem a ver com a maneira como o texto é armazenado - algo sobre o tamanho da página, acredito. A saída é na maior parte correto, mas cada agora e, em seguida, você recebe uma quebra de linha extra.
RolandTumble
13

Um truque de procedimento armazenado é que você pode chamá-los de uma instrução INSERT. Achei isso muito útil quando estava trabalhando em um banco de dados do SQL Server.

CREATE TABLE #toto (v1 int, v2 int, v3 char(4), status char(6))
INSERT #toto (v1, v2, v3, status) EXEC dbo.sp_fulubulu(sp_param1)
SELECT * FROM #toto
DROP TABLE #toto
edomaur
fonte
1
Infelizmente não pode ser usado com @TableVariable
Kristen
A dor desta técnica muito útil é que, diferentemente da maioria das tabelas de tabelas, você precisa definir todas as colunas completamente. A maneira preguiçosa de fazer isso é criar a #table dentro do proc que você está chamando no final e, em seguida, sp_help no tempdb, copiar e colar, remover o código do proc. Feito
adolf garlic
12

No SQL Server 2005/2008, para mostrar os números de linha em um resultado da consulta SELECT:

SELECT ( ROW_NUMBER() OVER (ORDER BY OrderId) ) AS RowNumber,
        GrandTotal, CustomerId, PurchaseDate
FROM Orders

ORDER BY é uma cláusula obrigatória. A cláusula OVER () informa ao SQL Engine para classificar os dados na coluna especificada (neste caso, OrderId) e atribuir números de acordo com os resultados da classificação.

Binoj Antony
fonte
não seria mais simples se eles usassem o sugestão sintático no mecanismo sql para analisá-la como "RowNumberInTable"
nenhum
1
+1 para funções da janela. Você pode executar
Matt Stephenson
10

Útil para analisar argumentos de procedimento armazenado: xp_sscanf

Lê dados da string nos locais dos argumentos especificados por cada argumento de formato.

O exemplo a seguir usa xp_sscanf para extrair dois valores de uma cadeia de origem com base em suas posições no formato da cadeia de origem.

DECLARE @filename varchar (20), @message varchar (20)
EXEC xp_sscanf 'sync -b -fproducts10.tmp -rrandom', 'sync -b -f%s -r%s', 
  @filename OUTPUT, @message OUTPUT
SELECT @filename, @message

Aqui está o conjunto de resultados.

-------------------- -------------------- 
products10.tmp        random
Sklivvz
fonte
4
Eu devo estar tendo um momento idiota (não, sério). Você pode me dizer onde podemos usar isso?
Raj
9

Somente data de retorno

Select Cast(Floor(Cast(Getdate() As Float))As Datetime)

ou

Select DateAdd(Day, 0, DateDiff(Day, 0, Getdate()))
GateKiller
fonte
Versão curta - SELECT CAST (PISO (CAST (@DateTime AS FLOAT)) AS DATETIME)
Meff 1/08/08
Claro que sim. Regras CASTFLOORCAST.
StingyJack
Não consigo encontrar uma referência a ele, mas me lembro dos testes que sugeriram que SELECT DateAdd (Day, 0, DateDiff (Day, 0, @DateTime)) era mais rápido. Feliz por ser esclarecido, de qualquer maneira!
217 Kristen Kristen
Encontrei este sqlteam.com/forums/topic.asp?TOPIC_ID=35296#107617, mas não incluiu o método CAST / FLOOR. Um teste informal sobre um conjunto de registros de tamanho médio sugere DATEADD pode ser cerca de 7% mais rápido do que ELENCO / CHÃO - não o suficiente para se preocupar para a maioria das situações
Kristen
Eu adicionei o outro método, no entanto; meus testes rápidos mostram que o método do piso fundido é 800 nanossegundos mais rápido. Então, nada realmente.
21339 GateKiller
9

dm_db_index_usage_stats

Isso permite que você saiba se os dados em uma tabela foram atualizados recentemente, mesmo se você não tiver uma coluna DateUpdated na tabela.

SELECT OBJECT_NAME(OBJECT_ID) AS DatabaseName, last_user_update,*
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID( 'MyDatabase')
AND OBJECT_ID=OBJECT_ID('MyTable')

Código de: http://blog.sqlauthority.com/2009/05/09/sql-server-find-last-date-time-updated-for-any-table/

Informações referenciadas em: SQL Server - Qual é a data / hora da última linha inserida de uma tabela?

Disponível no SQL 2005 e posterior

Nathan Koop
fonte
7

Aqui estão alguns recursos que considero úteis, mas muitas pessoas parecem não saber:

sp_tables

Retorna uma lista de objetos que podem ser consultados no ambiente atual. Isso significa qualquer objeto que possa aparecer em uma cláusula FROM, exceto objetos sinônimos.

Ligação

sp_stored_procedures

Retorna uma lista de procedimentos armazenados no ambiente atual.

Ligação

Sklivvz
fonte
7

Encontre registros cuja data esteja em algum lugar da semana atual.

where dateadd( week, datediff( week, 0, TransDate ), 0 ) =
dateadd( week, datediff( week, 0, getdate() ), 0 )

Encontre registros cuja data ocorreu na semana passada.

where dateadd( week, datediff( week, 0, TransDate ), 0 ) =
dateadd( week, datediff( week, 0, getdate() ) - 1, 0 )

Retorna a data para o início da semana atual.

select dateadd( week, datediff( week, 0, getdate() ), 0 )

Retorna a data do início da semana passada.

select dateadd( week, datediff( week, 0, getdate() ) - 1, 0 )
GateKiller
fonte
Fino, mas o índice no TransDate não seria usado. Eu preferiria escrever
vaso
em que TransDate> = convert (data e hora, andar (converter (flutuar, dateadd (dia, data-dia (dia da semana, @ data) +1, @ data)))) e TransDate> = converter (data e hora, andar (converter (flutuar, dateadd (day, 7-datepart (weekday, @date) +1, @date))))
vaso
correção: onde TransDate> = convert (data / hora, andar (converter (flutuar, dateadd (dia, data-dia (dia da semana, @ data) +1, @ data)))) e TransDate <converter (data / hora, andar (converter (flutuar, dateadd (day, 7-datepart (weekday, @date) +1, @date))))
vaso
7

Não é um recurso oculto, mas configura os mapeamentos de teclas no Management Studio em Ferramentas \ Opções \ Teclado: Alt + F1 é padronizado como sp_help "texto selecionado", mas não consigo viver sem adicionar Ctrl + F1 para sp_helptext "texto selecionado"

JohnD
fonte
Eu uso para configurar o comando USE, também, para se movendo ao longo da JC
Jhonny D. Cano -Leftware-
7

Colunas computadas persistentes

  • As colunas computadas podem ajudar a mudar o custo da computação em tempo de execução para a fase de modificação de dados. A coluna computada é armazenada com o restante da linha e é utilizada de forma transparente quando a expressão nas colunas calculadas e na consulta corresponde. Você também pode criar índices nos PCCs para acelerar as filtrações e realizar varreduras na expressão.

Ligação

Sklivvz
fonte
7

Há momentos em que não há coluna adequada para classificar, ou você apenas deseja a ordem de classificação padrão em uma tabela e deseja enumerar cada linha. Para fazer isso, você pode colocar "(selecione 1)" na cláusula "ordenar por" e obter o que deseja. Legal, não é?

select row_number() over (order by (select 1)), * from dbo.Table as t
Denis Valeev
fonte