Fonctionnalités cachées de SQL Server

215

Quelles sont les fonctionnalités cachées de SQL Server ?

Par exemple, des procédures stockées système non documentées, des astuces pour faire des choses qui sont très utiles mais pas suffisamment documentées?


Réponses

Merci à tous pour toutes les bonnes réponses!

Procédures stockées

  • sp_msforeachtable: exécute une commande avec '?' remplacé par chaque nom de table (v6.5 et plus)
  • sp_msforeachdb: exécute une commande avec '?' remplacé par chaque nom de base de données (v7 et plus)
  • sp_who2: tout comme sp_who, mais avec beaucoup plus d'informations pour le dépannage des blocs (v7 et plus)
  • sp_helptext: Si vous voulez le code d'une procédure stockée, affichez & UDF
  • sp_tables: retourne une liste de toutes les tables et vues de la base de données dans la portée.
  • sp_stored_procedures: retourne une liste de toutes les procédures stockées
  • xp_sscanf: lit les données de la chaîne dans les emplacements d'argument spécifiés par chaque argument de format.
  • xp_fixeddrives:: recherchez le lecteur fixe avec le plus grand espace libre
  • sp_help: si vous souhaitez connaître la structure, les index et les contraintes d'une table. Vues et UDF également. Le raccourci est Alt + F1

Extraits

  • Renvoyer des lignes dans un ordre aléatoire
  • Tous les objets utilisateur de la base de données par date de dernière modification
  • Date de retour uniquement
  • Recherchez les enregistrements dont la date se situe quelque part dans la semaine en cours.
  • Recherchez les enregistrements dont la date s'est produite la semaine dernière.
  • Renvoie la date du début de la semaine en cours.
  • Renvoie la date du début de la semaine dernière.
  • Voir le texte d'une procédure qui a été déployée sur un serveur
  • Supprimer toutes les connexions à la base de données
  • Table de contrôle
  • Somme de contrôle de ligne
  • Supprimer toutes les procédures dans une base de données
  • Remappez correctement les ID de connexion après la restauration
  • Appeler des procédures stockées à partir d'une instruction INSERT
  • Rechercher des procédures par mot-clé
  • Supprimer toutes les procédures dans une base de données
  • Recherchez par programme le journal des transactions d'une base de données.

Les fonctions

  • HashBytes ()
  • EncryptByKey
  • Commande PIVOT

Divers

  • Extras de chaîne de connexion
  • TableDiff.exe
  • Déclencheurs pour les événements d'ouverture de session (nouveau dans le Service Pack 2)
  • Amélioration des performances avec des colonnes calculées persistantes (pcc).
  • Paramètre DEFAULT_SCHEMA dans sys.database_principles
  • Paramétrage forcé
  • Format de stockage Vardecimal
  • Comprendre les requêtes les plus populaires en quelques secondes
  • Bases de données partagées évolutives
  • Fonction de filtrage des tables / procédures stockées dans SQL Management Studio
  • Drapeaux de trace
  • Numéro après une GOrépétition du lot
  • Sécurité à l'aide de schémas
  • Cryptage utilisant des fonctions de cryptage intégrées, des vues et des tables de base avec des déclencheurs
Sklivvz
la source
4
S'ils sont connus, il serait bon d'inclure les versions applicables à chaque réponse. (2000 et plus, 2005, 2000 seulement, etc.)
bw
Il y a beaucoup de bonté dans cette question. Veuillez ne pas le supprimer! :-)
Sklivvz

Réponses:

91

Dans Management Studio, vous pouvez mettre un nombre après un marqueur de fin de lot GO pour que le lot soit répété autant de fois:

PRINT 'X'
GO 10

Imprime «X» 10 fois. Cela peut vous éviter de copier / coller fastidieux lorsque vous faites des choses répétitives.

GilM
la source
70

De nombreux développeurs SQL Server ne semblent toujours pas connaître la clause OUTPUT (SQL Server 2005 et versions ultérieures) sur l'instruction DELETE, INSERT et UPDATE.

Il peut être extrêmement utile de savoir quelles lignes ont été INSERTed, UPDATEd ou DELETEd, et la clause OUTPUT permet de le faire très facilement - elle permet d'accéder aux tables "virtuelles" appelées insertedet deleted(comme dans les déclencheurs):

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

Si vous insérez des valeurs dans une table qui a un champ de clé primaire INT IDENTITY, avec la clause OUTPUT, vous pouvez obtenir le nouvel ID inséré immédiatement:

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

Et si vous mettez à jour, il peut être extrêmement utile de savoir ce qui a changé - dans ce cas, insertedreprésente les nouvelles valeurs (après la MISE À JOUR), tout en faisant deletedréférence aux anciennes valeurs avant la MISE À JOUR:

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

Si beaucoup d'informations seront retournées, la sortie de OUTPUT peut également être redirigée vers une table temporaire ou une variable de table ( OUTPUT INTO @myInfoTable).

Extrêmement utile - et très peu connu!

Marc

marc_s
la source
52

sp_msforeachtable: Exécute une commande avec '?' remplacé par chaque nom de table. par exemple

exec sp_msforeachtable "dbcc dbreindex('?')"

Vous pouvez émettre jusqu'à 3 commandes pour chaque table

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

Aussi, sp_MSforeachdb

blé Mitch
la source
2
Vous pouvez obtenir le nom de la table dans la requête en utilisant des guillemets simples autour du point d'interrogation. sp_msforeachtable "sélectionnez le nombre (*), '?' comme tabenm? "
Jody
51

Extras de chaîne de connexion:

MultipleActiveResultSets = true;

Cela permet à ADO.Net 2.0 et supérieur de lire plusieurs jeux de résultats en lecture seule et en avant sur une seule connexion de base de données, ce qui peut améliorer les performances si vous effectuez beaucoup de lecture. Vous pouvez l'activer même si vous faites un mélange de types de requêtes.

Nom de l'application = MyProgramName

Maintenant, lorsque vous souhaitez voir une liste des connexions actives en interrogeant la table sysprocesses, le nom de votre programme apparaîtra dans la colonne nom_programme au lieu de ".Net SqlClient Data Provider"

Chris Wenham
la source
7
J'ai fait du nom de l'application une exigence dans mon entreprise. Chaque nouvelle application doit avoir un nom unique. Rend la recherche de l'application verrouillée / cassée beaucoup plus facile.
Neil N
2
Le nom de l'application est également disponible sous forme de filtre dans le profileur. Cela aide beaucoup si vous ne souhaitez voir que vos requêtes et non les requêtes de vos collègues.
Mathias F
33

TableDiff.exe

  • L'outil Différence de table vous permet de découvrir et de réconcilier les différences entre une table source et de destination ou une vue. Tablediff Utility peut signaler des différences sur le schéma et les données. La fonctionnalité la plus populaire de tablediff est le fait qu'il peut générer un script que vous pouvez exécuter sur la destination qui rapprochera les différences entre les tables.

Lien

Sklivvz
la source
31

Une technique TSQL moins connue pour renvoyer des lignes dans un ordre aléatoire:

-- Return rows in a random order
SELECT 
    SomeColumn 
FROM 
    SomeTable
ORDER BY 
    CHECKSUM(NEWID())
blé Mitch
la source
6
Idéal pour les petits jeux de résultats. Je ne l'utiliserais pas sur une table avec plus de 10000 lignes, sauf si vous avez du temps à perdre
John Sheehan
Je l'ai utilisé sur des tables beaucoup plus grandes que ça, et ce n'était pas trop lent.
Mitch Wheat
Quel est le but du CHECKSUM ()? Vous pouvez commander par NEWID ().
Jonas Lincoln
6
J'ai même vu des résultats décents sur 100 000 000 (100 mil) lignes, sans CHECKSUM (). Aussi, je dois aussi demander pourquoi ne pas simplement COMMANDER PAR NEWID?
Troy DeMonbreun
5
@GateKiller: J'ai annulé votre modification, car la somme de contrôle () n'est pas une erreur; il réduit la taille de la colonne de tri.
Mitch Wheat,
30

Dans Management Studio, vous pouvez obtenir rapidement une liste de colonnes séparées par des virgules pour une table en:

  1. Dans l'Explorateur d'objets, développez les nœuds sous une table donnée (vous verrez donc des dossiers pour les colonnes, les clés, les contraintes, les déclencheurs, etc.)
  2. Pointez sur le dossier Colonnes et faites-le glisser dans une requête.

C'est pratique lorsque vous ne voulez pas utiliser le format odieux renvoyé en cliquant avec le bouton droit sur la table et en choisissant Script Table As ..., puis Insert To ... Cette astuce fonctionne avec les autres dossiers en ce qu'elle vous donnera une liste de noms séparés par des virgules contenus dans le dossier.

Thomas
la source
23

Constructeurs de lignes

Vous pouvez insérer plusieurs lignes de données avec une seule instruction d'insertion.

INSERT INTO Colors (id, Color)
VALUES (1, 'Red'),
       (2, 'Blue'),
       (3, 'Green'),
       (4, 'Yellow')
Rob Boek
la source
J'ai voté pour cela, mais je l'ai ensuite essayé dans MSSQL 2005 et cela ne fonctionne pas. 2008 seulement?
richardtallent
11
Oui, c'est une nouvelle fonctionnalité de 2008.
Rob Boek
2
C'est une fonctionnalité qui m'a manqué lorsque je suis passé de DB2 à SQL Server. Dans DB2, il y a eu une amélioration significative de la vitesse lors de l'utilisation de ceci au lieu des instructions d'insertion individuelles
Nathan Koop
22

Si vous souhaitez connaître la structure de la table, les index et les contraintes:

sp_help 'TableName'
Eduardo Molteni
la source
Combinez cette astuce avec sa touche de raccourci! Mettez d'abord un nom de tableau en surbrillance, puis appuyez sur ALT + F1
Michael J Swart
22

HashBytes () pour renvoyer le hachage MD2, MD4, MD5, SHA ou SHA1 de son entrée.

Joel Coehoorn
la source
Joli! Le lien correct est msdn.microsoft.com/en-us/library/ms174415(SQL.90).aspx (version 2005)
Sklivvz
Vous avez raison, c'était la version 2008 de la documentation, même si les pages sont à peu près identiques. Fixé maintenant.
Joel Coehoorn
20

Déterminer les requêtes les plus populaires

  • Avec sys.dm_exec_query_stats, vous pouvez déterminer de nombreuses combinaisons d'analyses de requêtes par une seule requête.

Lien avec la commnade

select * from sys.dm_exec_query_stats 
order by execution_count desc
Sklivvz
la source
17

L'onglet des résultats spatiaux peut être utilisé pour créer de l'art .

entrez la description du lien ici http://michaeljswart.com/wp-content/uploads/2010/02/venus.png

Martin Smith
la source
7
J'ai vu Jésus dans mes résultats de recherche!
P Daddy
6
Pfff ... Quel connard perd son temps à jouer avec l'onglet des résultats spatiaux. Oh, attendez ... Vous savez, je pensais que ce post semblait familier, maintenant je me souviens pourquoi.
Michael J Swart
16

SAUF et INTERSECT

Au lieu d'écrire des jointures et des sous-requêtes élaborées, ces deux mots clés sont un raccourci beaucoup plus élégant et un moyen lisible d'exprimer l'intention de votre requête lors de la comparaison de deux résultats de requête. Nouveautés de SQL Server 2005, elles complètent fortement UNION qui existe déjà depuis des années dans le langage TSQL.

Les concepts EXCEPT, INTERSECT et UNION sont fondamentaux dans la théorie des ensembles qui sert de base et de fondement à la modélisation relationnelle utilisée par tous les SGBDR modernes. Désormais, les résultats de type diagramme de Venn peuvent être générés de manière plus intuitive et assez facile à l'aide de TSQL.

Ray Vega
la source
16

Je sais que ce n'est pas exactement caché, mais pas trop de gens connaissent la commande PIVOT . J'ai pu modifier une procédure stockée qui utilisait des curseurs et j'ai pris 2 minutes pour exécuter un morceau de code rapide de 6 secondes, soit un dixième du nombre de lignes!

Ronald Wildenberg
la source
16

utile lors de la restauration d'une base de données à des fins de test ou autre. Re-mappe correctement l'ID de connexion:

EXEC sp_change_users_login 'Auto_Fix', 'Mary', NULL, 'B3r12-36'
Kolten
la source
J'ai eu ce proc ne fonctionnait pas avant, et j'ai dû changer la propriété des objets à un utilisateur temporaire, supprimer l'utilisateur d'origine, rajouter l'original et attribuer la propriété. Ugh ...
StingyJack
15

Supprimez toutes les connexions à la base de données:

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
la source
Existe-t-il un one-liner ou un paramètre de base de données de dépôt qui fait cela pour moi? Je remarque que si vous essayez de «supprimer la base de données» via l'interface utilisateur, il y a une case à cocher pour «fermer les connexions existantes», ce qui implique qu'il s'agit d'un paramètre booléen.
DevinB
1
En fait, je viens de trouver une solution à deux lignes. ALTER DATABASE [@ DATABASE_NAME @] SET READ_ONLY WITH ROLLBACK IMMEDIATE - cela déconnecte tous les utilisateurs ALTER DATABASE [@ DATABASE_NAME @] SET READ_WRITE WITH ROLLBACK IMMEDIATE DROP DATABASE [@ DATABASE_NAME @]
DevinB 17
1
ALTER DATABASE MyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATEempêchera également toute nouvelle connexion de se produire.
ErikE
15

Table de contrôle

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

Somme de contrôle de ligne

Select CheckSum_Agg(Binary_CheckSum(*)) From Table With (NOLOCK) Where Column = Value
GateKiller
la source
2
Ceux-ci vous permettent de produire une somme de contrôle pour toutes les données du tableau. C'est un moyen simple et rapide de vérifier si deux lignes ou deux tableaux sont identiques.
GateKiller
15

Je ne sais pas si c'est une fonctionnalité cachée ou non, mais je suis tombé sur cela et l'ai trouvé utile à de nombreuses reprises. Vous pouvez concaténer un ensemble d'un champ dans une seule instruction select, plutôt que d'utiliser un curseur et de parcourir cette instruction select.

Exemple:

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

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

SELECT @nvcConcatonated

Résultats:

Acme, Microsoft, Apple,
Sheki
la source
2
vous pouvez également utiliser COALESCE () pour faire la même chose sans avoir à initialiser la variable. SELECT @nvcConcatonated = COALESCE (@nvcConcatonated + ',', '') + CAST (C.CompanyName as VARCHAR (255)) FROM ...
Christopher Klein
Cela fonctionne également dans une déclaration de mise à jour. Parfois utile pour faire des choses comme concaténer une liste d'ID qui ont été mis à jour.
EBarr
14

Si vous voulez le code d'une procédure stockée, vous pouvez:

sp_helptext 'ProcedureName'

(je ne sais pas si c'est une fonction cachée, mais je l'utilise tout le temps)

Eduardo Molteni
la source
Je ne sais pas pourquoi, mais la sortie de sp_helptext est un peu maladroite sur les lignes trop longues de l'original. Lorsque vous écrivez des Sprocs, cela ne se produit pas, alors peut-être qu'il existe un autre mécanisme d'exportation, plus robuste? sp_helptext 'MyView' est également utile.
Kristen
Je ne sais pas ce que tu veux dire. Pour moi, le code des SP est sorti avec le même format que je les ai scriptés dans le fichier d'origine (avec tous les CR, etc.)
Eduardo Molteni
Je ne me souviens pas des détails exacts , mais cela a à voir avec la façon dont le texte est stocké - quelque chose sur la taille de la page, je crois. La sortie est généralement correcte, mais de temps en temps vous obtenez un saut de ligne supplémentaire.
RolandTumble
13

Une astuce de procédure stockée est que vous pouvez les appeler à partir d'une instruction INSERT. J'ai trouvé cela très utile lorsque je travaillais sur une base de données 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
la source
1
Malheureusement, ne peut pas être utilisé avec @TableVariable
Kristen
Le problème avec cette technique très utile est que, contrairement à la plupart des #tables, vous devez définir entièrement toutes les colonnes. La manière paresseuse de le faire est de créer la #table à l'intérieur du proc que vous appelez à la fin, puis sp_help dans tempdb, copiez et collez, supprimez le code de proc. Fait
Adolf Garlic
12

Dans SQL Server 2005/2008 pour afficher les numéros de ligne dans un résultat de requête SELECT:

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

COMMANDER PAR est une clause obligatoire. La clause OVER () indique au moteur SQL de trier les données sur la colonne spécifiée (dans ce cas, OrderId) et d'attribuer des numéros conformément aux résultats du tri.

Binoj Antony
la source
ne serait pas plus simple s'ils utilisaient un mot syntaxique dans le moteur SQL pour analyser le mot de syntaxe comme "RowNumberInTable"
aucun
1
+1 pour les fonctions de fenêtre. Vous pouvez faire des choses SUR un sous-ensemble d'enregistrements en utilisant OVER (PARTITION BY ...) msdn.microsoft.com/en-us/library/ms189461%28v=SQL.100%29.aspx
Matt Stephenson
10

Utile pour analyser les arguments des procédures stockées: xp_sscanf

Lit les données de la chaîne dans les emplacements d'argument spécifiés par chaque argument de format.

L'exemple suivant utilise xp_sscanf pour extraire deux valeurs d'une chaîne source en fonction de leur position au format de la chaîne source.

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

Voici l'ensemble de résultats.

-------------------- -------------------- 
products10.tmp        random
Sklivvz
la source
4
Je dois avoir un moment stupide (non, vraiment). Pouvez-vous me dire où nous pouvons utiliser cela?
Raj More
9

Date de retour uniquement

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

ou

Select DateAdd(Day, 0, DateDiff(Day, 0, Getdate()))
GateKiller
la source
Version courte - SÉLECTIONNER CAST (FLOOR (CAST (@DateTime AS FLOAT)) AS DATETIME)
Meff
Putain, oui. Règles CASTFLOORCAST.
StingyJack
Impossible de trouver une référence, mais je semble me souvenir des tests qui ont suggéré que SELECT DateAdd (Day, 0, DateDiff (Day, 0, @DateTime)) était plus rapide. Heureux d'être éclairé, de toute façon!
Kristen
Vous avez trouvé ce sqlteam.com/forums/topic.asp?TOPIC_ID=35296#107617 mais il n'a pas inclus la méthode CAST / FLOOR. Un test informel sur un jeu d'enregistrements de taille moyenne suggère que DATEADD peut être environ 7% plus rapide que CAST / FLOOR - pas assez pour s'inquiéter dans la plupart des situations
Kristen
J'ai cependant ajouté l'autre méthode; mes tests rapides montrent que la méthode du plancher coulé est plus rapide de 800 nanosecondes. Donc rien dedans vraiment.
GateKiller
9

dm_db_index_usage_stats

Cela vous permet de savoir si les données d'une table ont été mises à jour récemment même si vous n'avez pas de colonne DateUpdated sur la table.

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')

Code depuis: http://blog.sqlauthority.com/2009/05/09/sql-server-find-last-date-time-updated-for-any-table/

Informations référencées à partir de: SQL Server - Quelle est la date / heure de la dernière ligne insérée d'une table?

Disponible dans SQL 2005 et versions ultérieures

Nathan Koop
la source
7

Voici quelques fonctionnalités que je trouve utiles mais que beaucoup de gens ne semblent pas connaître:

sp_tables

Renvoie une liste d'objets pouvant être interrogés dans l'environnement actuel. Cela signifie tout objet pouvant apparaître dans une clause FROM, à l'exception des objets synonymes.

Lien

sp_stored_procedures

Renvoie une liste des procédures stockées dans l'environnement actuel.

Lien

Sklivvz
la source
7

Recherchez les enregistrements dont la date se situe quelque part dans la semaine en cours.

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

Recherchez les enregistrements dont la date s'est produite la semaine dernière.

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

Renvoie la date du début de la semaine en cours.

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

Renvoie la date du début de la semaine dernière.

select dateadd( week, datediff( week, 0, getdate() ) - 1, 0 )
GateKiller
la source
Bien mais l'index sur TransDate ne serait pas utilisé. Je préfère écrire
vaso
où TransDate> = convert (datetime, floor (convert (float, dateadd (day, -datepart (week-end, @date) +1, @date))))) et TransDate> = convert (datetime, floor (convert (float, dateadd (jour, partie à 7 dates (jour de semaine, @date) +1, @date))))
vaso
correction: où TransDate> = convert (datetime, floor (convert (float, dateadd (day, -datepart (week-end, @date) +1, @date)))) et TransDate <convert (datetime, floor (convert (float, dateadd (jour, partie à 7 dates (jour de semaine, @date) +1, @date))))
vaso
7

Pas tellement une fonctionnalité cachée mais la configuration des mappages de touches dans Management Studio sous Tools \ Options \ Keyboard: Alt + F1 est défini par défaut sur sp_help "texte sélectionné" mais je ne peux pas vivre sans l'ajout de Ctrl + F1 pour sp_helptext "texte sélectionné"

JohnD
la source
J'utilise également pour configurer la commande USE, pour se déplacer le long des bases de données
Jhonny D. Cano -Leftware-
7

Colonnes calculées persistantes

  • Les colonnes calculées peuvent vous aider à déplacer le coût de calcul d'exécution vers la phase de modification des données. La colonne calculée est stockée avec le reste de la ligne et est utilisée de manière transparente lorsque l'expression sur les colonnes calculées et la requête correspondent. Vous pouvez également créer des index sur les PCC pour accélérer les filtrations et les analyses de plage sur l'expression.

Lien

Sklivvz
la source
7

Il y a des moments où il n'y a pas de colonne appropriée pour trier, ou vous voulez simplement l'ordre de tri par défaut sur une table et vous voulez énumérer chaque ligne. Pour ce faire, vous pouvez mettre "(sélectionnez 1)" dans la clause "order by" et vous obtiendrez ce que vous voulez. Neat, hein?

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