2017-07-06 10 views
0

J'ai besoin de trouver des numéros manquants dans ma base de données. Je compare deux bases de données, tempdb créé dans la requête avec les nombres 1 - 999 et MYDAT.Erreur SQL lors de la conversion de varchar en int en joignant deux tables

MYDAT ressemble:

+-------+ 
| id | 
+-------+ 
| A-001 | 
| A-002 | 
| A-004 | 
| A-... | 
| A-952 | 
| A-... | 
+-------+ 

Je cours cette requête:

declare @tempid int 

set @tempid = 1 

create table tempdb (tempid int) 

while @tempid < 1000 
begin 
    insert into tempdb values(@tempid) 
    set @tempid = @tempid + 1 
end 

select tempdb.tempid from tempdb 
left join MYDAT on tempdb.tempid = CAST(SUBSTRING(MYDAT.ID, 3, 3) as INT) 
where 
MYDAT.ID IS NULL and 
SUBSTRING(MYDAT.ID, 3, 3) <> '' and 
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and 
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%' 

drop table tempdb 

Sans droping temdb, select * from tempdb semble bon et je reçois ce que je veux.

La partie avec la sélection et la conversion des données à partir MYDAT fonctionne bien et je reçois seulement des entiers

select CAST(SUBSTRING(MYDAT.ID, 3, 3) as INT) fom MYDAT 
where 
SUBSTRING(MYDAT.ID, 3, 3) <> '' and 
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and 
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%' 

Je reçois une erreur « conversion varchar int » mais je ne sais pas pourquoi. Quand je change de jointure gauche à droite, je ne reçois aucune erreur.

J'ai également vérifié les deux bases de données manuellement et il n'y a pas de chaînes ou caractères, seuls les entiers.

J'ai également essayé le CONVERT() mais avec le même résultat.

Des suggestions ou des idées quel est le problème?

Edit:

1 - Je vois une erreur que je l'ai essayé sur rextester. I added MYDAT.ID IS NULL à la requête afin que j'obtienne des résultats corrects.

2 - Exemples Je en ai besoin: http://rextester.com/KFG73206

Mais CAST ou CONVERT juste ne semble pas fonctionner http://rextester.com/WJIAH52304

+0

Marquez les dbms que vous utilisez. (Certaines constructions spécifiques au produit ici ...) – jarlh

+0

Ce n'est pas évident pour moi pourquoi vous obtenez cette erreur. Pouvez-vous créer une démo pour nous sur [Rextester] (http://www.rextester.com) et coller le lien ici? –

+0

http://rextester.com/CSY70642 La seule chose que je peux penser est ID dans MYDAT n'est pas ce que vous pensez .. Comme cela ressemble à ça fonctionne .. comment ID est défini dans le schéma - type, longueur, etc. – JGFMK

Répondre

1

Vous avez dit 'numéros manquants' alors les choses dans tempdb qui ne sont pas dans MYDAT sont ce que vous recherchez?Si oui, voyez: http://rextester.com/HCB88714

+0

PAS IN() ... très intelligent ... merci beaucoup – user2463808

0

Ne peut pas clairement la cause, peut-être un problème avec les données. Vous pouvez essayer pour une solution de contournement pour éviter la coulée,

create table tempdb (tempid varchar(3)) 

while @tempid < 1000 
begin 
    insert into tempdb values(@tempid) 
    set @tempid = @tempid + 1 
end 

select tempdb.tempid from tempdb 
left join MYDAT on tempdb.tempid = SUBSTRING(MYDAT.ID, 3, 3) 
where 
SUBSTRING(MYDAT.ID, 3, 3) <> '' and 
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and 
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%' 
0

Le problème est que la clause where est pas nécessairement exécuté avant la clause on. SQL Server peut réorganiser les opérations.

Je suppose que vous voulez vraiment comparer aux trois premiers caractères de MYDAT.ID. Cela simplifie un peu les choses, car vous pouvez utiliser LEFT() comme dans le code ci-dessous. En fait, vos conditions where ne semblent pas correctes, alors je les ai corrigées.

La meilleure solution est try_convert():

select tempdb.tempid 
from tempdb left join 
    MYDAT 
    on tempdb.tempid = try_convert(int, left(MYDAT.ID, 3)) 
where MYDAT.ID <> '' and 
     left(MYDAT.ID, 3) <> '000' and 
     left(MYDAT.ID, 3) NOT LIKE '%[^0-9]%'; 

pré-SQL Server 2012 versions, vous pouvez utiliser un case à la place:

select tempdb.tempid 
from tempdb left join 
    MYDAT 
    on tempdb.tempid = (case when left(MYDAT.ID, 1, 3) not like '%[^0-9]%') 
           then convert(int, left(MYDAT.ID, 3) 
         end) 
where MYDAT.ID <> '' and 
     left(MYDAT.ID, 3) <> '000' and 
     left(MYDAT.ID, 3) NOT LIKE '%[^0-9]%'; 

case ne garantit l'ordre d'évaluation.