J'ai une table de noms et d'adresses, qui comprend une colonne de code postal. Je souhaite supprimer les espaces des codes postaux et sélectionner ceux qui correspondent à un modèle particulier. J'essaie ceci (un peu simplifié) dans T-SQL sur SQL Server 2005:
SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE P LIKE 'NW101%'
Mais je reçois l'erreur suivante;
Msg 207, Level 16, State 1, Line 3
Invalid column name 'P'.
Si je supprime la clause WHERE, je reçois une liste de codes postaux sans espaces, ce que je souhaite rechercher. Comment devrais-je aborder cela? Qu'est-ce que je fais mal?
N'utilisez pas l'alias (P
) directement dans votre clause WHERE
.
Vous pouvez utiliser à nouveau la même logique REPLACE
dans la clause WHERE
:
SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%'
Ou utilisez une sous-requête avec alias comme décrit dans les réponses de Nick.
Vous pouvez faire référence à cette façon si vous enroulez la requête, comme ceci:
SELECT P
FROM (SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts) innertable
WHERE P LIKE 'NW101%'
Assurez-vous de donner à la sélection enveloppée un alias, même inutilisé (SQL Server ne le permet pas sans un IIRC)
Vous créez un alias P
et plus tard dans la clause where
vous utilisez le même, c’est ce qui crée le problème. N'utilisez pas P
dans where
, essayez plutôt ceci:
SELECT Replace(Postcode, ' ', '') AS P FROM Contacts
WHERE Postcode LIKE 'NW101%'
Pour développer la réponse de Oded , votre modèle conceptuel nécessite un léger ajustement ici. La création d'alias de noms de colonnes (clauses AS
dans la liste SELECT
) intervient très tard dans le traitement d'une SELECT
, raison pour laquelle les noms d'alias ne sont pas disponibles pour les clauses WHERE
. En fait, la seule chose qui se passe après le repliement des colonnes est le tri, ce qui explique pourquoi (pour citer les docs sur SELECT
):
column_alias
peut être utilisé dans une clause ORDER BY. Cependant, il ne peut pas être utilisé dans une clauseWHERE
,GROUP BY
ouHAVING
.
Si vous avez une expression compliquée dans la liste SELECT
, vous craignez peut-être qu'elle soit «évaluée deux fois» lorsqu'elle apparaît dans la liste SELECT
et (disons) une clause WHERE
- cependant, le moteur de requête est assez intelligent pour comprendre ce qui se passe sur. Si vous voulez éviter que l'expression apparaisse deux fois dans votre requête, vous pouvez faire quelque chose comme:
SELECT c1, c2, c3, expr1
FROM
( SELECT c1, c2, c3, some_complicated_expression AS expr1 ) inner
WHERE expr1 = condition
ce qui évite que some_complicated_expression
apparaisse physiquement deux fois.
si vous souhaitez avoir un espoir d'utiliser un index, stockez les données de manière cohérente (sans les espaces). Supprimez simplement les espaces ou ajoutez une colonne calculée persistante. Vous pouvez alors simplement sélectionner dans cette colonne et ne pas avoir à ajouter tout l'espace en supprimant la surcharge chaque fois que vous exécutez votre requête.
ajoutez une colonne calculée PERSISTED:
ALTER TABLE Contacts ADD PostcodeSpaceFree AS Replace(Postcode, ' ', '') PERSISTED
go
CREATE NONCLUSTERED INDEX IX_Contacts_PostcodeSpaceFree
ON Contacts (PostcodeSpaceFree) --INCLUDE (covered columns here!!)
go
pour simplement corriger la colonne en supprimant les espaces, utilisez:
UPDATE Contacts
SET Postcode=Replace(Postcode, ' ', '')
maintenant vous pouvez chercher comme ceci, soit sélectionnez peut utiliser un index:
--search the PERSISTED computed column
SELECT
PostcodeSpaceFree
FROM Contacts
WHERE PostcodeSpaceFree LIKE 'NW101%'
ou
--search the fixed (spaces removed column)
SELECT
Postcode
FROM Contacts
WHERE PostcodeLIKE 'NW101%'
SELECT *
FROM Contacts
WHERE ContactId IN
(SELECT a.ContactID
FROM
(SELECT ContactId, Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Postcode LIKE '%N%W%1%0%1%') a
WHERE a.P LIKE 'NW101%')
Vous devez répéter votre expression partout où vous voulez l'utiliser:
SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%'
ou vous pouvez en faire une sous-requête
select P
from (
SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
) t
WHERE P LIKE 'NW101%'
Cela fonctionnera:
SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%'