Nous tous qui travaillons avec des bases de données relationnelles ont appris (ou d'apprentissage) que SQL est différent. Obtenir le résultat souhaité, et de le faire de manière efficace, implique un processus fastidieux en partie caractérisé par l'apprentissage inconnu paradigmes, et de découvrir que certains de nos plus familier des modèles de programmation ne fonctionnent pas ici. Quelles sont les communes antipatterns vous avez vu (ou vous-même engagé)?
Réponses
Trop de publicités?Je suis systématiquement déçu par la plupart des programmeurs tendance à mélanger leur INTERFACE utilisateur logique dans la couche d'accès aux données:
SELECT
FirstName + ' ' + LastName as "Full Name",
case UserRole
when 2 then "Admin"
when 1 then "Moderator"
else "User"
end as "User's Role",
case SignedIn
when 0 then "Logged in"
else "Logged out"
end as "User signed in?",
Convert(varchar(100), LastSignOn, 101) as "Last Sign On",
DateDiff('d', LastSignOn, getDate()) as "Days since last sign on",
AddrLine1 + ' ' + AddrLine2 + ' ' + AddrLine3 + ' ' +
City + ', ' + State + ' ' + Zip as "Address",
'XXX-XX-' + Substring(
Convert(varchar(9), SSN), 6, 4) as "Social Security #"
FROM Users
Normalement, les programmeurs font cela parce qu'ils ont l'intention de se lier leurs données directement sur une grille, et son juste commode de disposer de SQL Server format de serveur-côté que le format sur le client.
Des requêtes comme celle montrée ci-dessus sont extrêmement fragiles parce qu'ils couplent la couche de données à la couche d'INTERFACE utilisateur. De plus, ce style de programmation soigneusement évite des procédures stockées d'être réutilisable.
Voici mon top 3.
Numéro 1. L'échec de spécifier une liste de champs. (Edit: pour éviter la confusion: c'est un code de production de la règle. Il ne s'applique pas à des scripts d'analyse - à moins que je suis l'auteur.)
SELECT *
Insert Into blah SELECT *
devrait être
SELECT fieldlist
Insert Into blah (fieldlist) SELECT fieldlist
Numéro 2. À l'aide d'un curseur et d'une boucle while, lorsqu'une boucle while avec une variable de boucle va faire.
DECLARE @LoopVar int
SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable)
WHILE @LoopVar is not null
BEGIN
-- Do Stuff with current value of @LoopVar
...
--Ok, done, now get the next value
SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable
WHERE @LoopVar < TheKey)
END
Numéro 3. DateLogic à travers des types de chaînes.
--Trim the time
Convert(Convert(theDate, varchar(10), 121), datetime)
Devrait être
--Trim the time
DateAdd(dd, DateDiff(dd, 0, theDate), 0)
J'ai vu une hausse récente de "Une requête est mieux que deux, amiright?"
SELECT *
FROM blah
WHERE (blah.Name = @name OR @name is null)
AND (blah.Purpose = @Purpose OR @Purpose is null)
Cette requête nécessite deux ou trois différents plans d'exécution en fonction des valeurs des paramètres. Un seul plan d'exécution est générée et coincé dans le cache de ce texte sql. Ce plan sera utilisée quelle que soit la valeur des paramètres. Il en résulte intermittent de la mauvaise performance. Il est beaucoup mieux d'écrire deux requêtes (une requête prévu par le plan d'exécution).
Lisible par les champs de mot de passe, egad. Auto-explicatif.
En utilisant COMME contre indexés les colonnes, et je suis presque tenté de juste dire, COMME en général.
Recyclage SQL généré valeurs de clé primaire.
Surprise, personne n'a mentionné l' dieu-table encore. Rien ne dit "organiques" comme 100 colonnes de bit les drapeaux, les grandes chaînes et les nombres entiers.
Puis il y a les "je m'ennuie .ini les fichiers" modèle: stockage de ces volumes, pipe délimité par des chaînes ou d'autres parse les données requises dans les grands champs de texte.
Et pour MS SQL server à l'utilisation de les curseurs à tous. Il y a un mieux façon de le faire tout le curseur de la tâche.
Modifié, car il ya tellement de nombreux!