Discussione:
Conversione da Char a Numeric
(troppo vecchio per rispondere)
BuonAngolo
2005-01-25 14:50:22 UTC
Permalink
Ambiente: SQL2kSP3 su W2kSrvSP4.

In alcuni linguaggi di programmazione, esiste la funzione VAL, che
restituisce il valore numerico interprentando una stringa, e arrestando tale
valutazione al primo carattere non valido.
Cioè, VAL("123ABC") restituisce il valore numerico 123.

In T-SQL, la conversione di "123ABC" con un cast, restituisce errore (e mi
sembra più che logico).

Il mio problema è che ho dei codici articolo che ricevo da applicativi
diversi, e che mi vengono scritti in una tabella in un campo di tipo Char,
ma che in realtà sono sempre dei numeri seguiti da delle lettere.
Ad esempio, ho "123456LH" o "6575875ABC".

Le lettere a fine stringa sono 'anomalie', cioè devo di fatto non
considerarle.
Per questo, mi occorre nei join fare riferimento solo alla parte numerica
intesa come valore, cioè "000123ABC" deve soddisfare il join con un campo
numeric che vale 123.

Ho tentato questo
update tb_info_aggiuntive
set codice_numerico=cast(codice as numeric(18,0))

per poter poi usare [Codice_Numerico] come criterio di join, ma ovviamente
si arresta con errore.

Esiste la possibilità, in T-Sql, di ottenere il valore numerico della parte
numerica di un campo char, 'trascurando' le lettere finali?

Grazie

Alberto
--
E non so se avrò gli amici a farmi il coro,
o se avrò soltanto volti sconosciuti,
canterò le mia canzoni a tutti loro
e alla fine della strada
potrò dire che i miei giorni li ho vissuti
BuonAngolo
2005-01-25 14:54:22 UTC
Permalink
Post by BuonAngolo
Per questo, mi occorre nei join fare riferimento solo alla parte
numerica intesa come valore, cioè "000123ABC" deve soddisfare il join
con un campo numeric che vale 123.
Dimenticavo: Potrei avere anche cose tipo "000123ABC432", per cui non sono
riuscito a ottenere un join 'deterministico' usando il Like e inserendo il
numerico, convertito in char, fra due '%'.

Ciao

Alberto
--
E non so se avrò gli amici a farmi il coro,
o se avrò soltanto volti sconosciuti,
canterò le mia canzoni a tutti loro
e alla fine della strada
potrò dire che i miei giorni li ho vissuti
Andrea Montanari
2005-01-25 15:01:37 UTC
Permalink
salve Alberto,
Post by BuonAngolo
Dimenticavo: Potrei avere anche cose tipo "000123ABC432", per cui non
"000123ABC432" deve essere inteso come valore valido nel senso di "000123" +
"432" , per cui "000123432" ovvero solo come "000123" o "432" ?

saluti
--
Andrea Montanari (Microsoft MVP - SQL Server)
http://www.asql.biz/DbaMgr.shtm http://italy.mvps.org
DbaMgr2k ver 0.10.0 - DbaMgr ver 0.56.0
(my vb6+sql-dmo little try to provide MS MSDE 1.0 and MSDE 2000 a visual
interface)
--------- remove DMO to reply
Albe V°
2005-01-25 15:06:56 UTC
Permalink
Post by Andrea Montanari
salve Alberto,
Post by BuonAngolo
Dimenticavo: Potrei avere anche cose tipo "000123ABC432", per cui non
"000123ABC432" deve essere inteso come valore valido nel senso di
"000123" + "432" , per cui "000123432" ovvero solo come "000123" o
"432" ?
"000123ABC432" è valore valido che deve essere interpretato come 123.
Quando trovo un carattere non numerico, devo terminare l'interpretazione.

Ciao

Alberto
--
E tutto mi sembrava andasse bene...
Sandro Bizioli
2005-01-25 15:02:41 UTC
Permalink
Post by BuonAngolo
Post by BuonAngolo
Per questo, mi occorre nei join fare riferimento solo alla parte
numerica intesa come valore, cioè "000123ABC" deve soddisfare il
join con un campo numeric che vale 123.
Dimenticavo: Potrei avere anche cose tipo "000123ABC432", per cui
non sono riuscito a ottenere un join 'deterministico' usando il
Like e inserendo il numerico, convertito in char, fra due '%'.
Potresti utilizzare un campo calcolato dove utilizzi una funzione
utente che fa il parser della stringa (ad esempio utilizzando
charindex) e ripulendola (con le appripriate case) dalle parti non
numeriche.
Una volta pulita la stringa ne esegui le join che ti interessano
--
===========================
Sandro Bizioli
===========================
BuonAngolo
2005-01-25 15:07:45 UTC
Permalink
Post by Sandro Bizioli
Potresti utilizzare un campo calcolato dove utilizzi una funzione
utente che fa il parser della stringa (ad esempio utilizzando
charindex) e ripulendola (con le appripriate case) dalle parti non
numeriche.
Emh, diciamo che me la tenevo come ultima spiaggia...
Se si trova qualcosa di più o meno intrinseco in T-Sql, vado con quello...

Ciao

Alberto
--
E non so se avrò gli amici a farmi il coro,
o se avrò soltanto volti sconosciuti,
canterò le mia canzoni a tutti loro
e alla fine della strada
potrò dire che i miei giorni li ho vissuti
AlessandroD
2005-01-25 16:04:53 UTC
Permalink
Post by BuonAngolo
Ambiente: SQL2kSP3 su W2kSrvSP4.
In alcuni linguaggi di programmazione, esiste la funzione VAL, che
restituisce il valore numerico interprentando una stringa, e arrestando tale
valutazione al primo carattere non valido.
Cioè, VAL("123ABC") restituisce il valore numerico 123.
In T-SQL, la conversione di "123ABC" con un cast, restituisce errore (e mi
sembra più che logico).
Il mio problema è che ho dei codici articolo che ricevo da applicativi
diversi, e che mi vengono scritti in una tabella in un campo di tipo Char,
ma che in realtà sono sempre dei numeri seguiti da delle lettere.
Ad esempio, ho "123456LH" o "6575875ABC".
Le lettere a fine stringa sono 'anomalie', cioè devo di fatto non
considerarle.
Per questo, mi occorre nei join fare riferimento solo alla parte numerica
intesa come valore, cioè "000123ABC" deve soddisfare il join con un campo
numeric che vale 123.
Ho tentato questo
update tb_info_aggiuntive
set codice_numerico=cast(codice as numeric(18,0))
per poter poi usare [Codice_Numerico] come criterio di join, ma ovviamente
si arresta con errore.
Esiste la possibilità, in T-Sql, di ottenere il valore numerico della parte
numerica di un campo char, 'trascurando' le lettere finali?
Puoi adattare questo esempio che utilizza patindex() per ricavare il primo
carattere non numerico:


declare @tbl table (
TESTO varchar (100)
)


insert into @tbl values ('123456LH')
insert into @tbl values ('6575875ABC')
insert into @tbl values ('000123ABC')
insert into @tbl values ('000123ABC')
insert into @tbl values ('000123ABC432')
insert into @tbl values ('1258')
insert into @tbl values ('ABCD223')

select
TESTO,
convert (int,
left (TESTO, isnull (nullif (patindex ('%[^0-9]%', TESTO), 0), 1) -
1)
)
from @tbl

output:

123456LH 123456
6575875ABC 6575875
000123ABC 123
000123ABC 123
000123ABC432 123
1258 0
ABCD223 0

Ciao, Alessandro
AlessandroD
2005-01-25 16:12:11 UTC
Permalink
Post by AlessandroD
[...]
Puoi adattare questo esempio che utilizza patindex() per ricavare il primo
[...]
Mi correggo, ho postato troppo in fretta e mi è scappata una castronata...

select
TESTO,
convert (int,
left (TESTO, isnull (nullif (patindex ('%[^0-9]%', TESTO), 0),
len(TESTO) + 1) - 1)
)
from @tbl

output corretto:

123456LH 123456
6575875ABC 6575875
000123ABC 123
000123ABC 123
000123ABC432 123
1258 1258
ABCD223 0


Spero sia l'unica :-)
Ciao, Alessandro
Luca Bianchi
2005-01-25 16:23:00 UTC
Permalink
Post by AlessandroD
select
TESTO,
convert (int,
left (TESTO, isnull (nullif (patindex ('%[^0-9]%', TESTO), 0),
len(TESTO) + 1) - 1)
)
Si può semplificare scrivendo
SELECT LEFT(testo, PATINDEX ('%[^0-9]%', testo) -1)
Post by AlessandroD
Spero sia l'unica :-)
Ciao, Alessandro
Bye
--
Luca Bianchi
Microsoft MVP - SQL Server
Windows Development Day - Bologna 28/01/2005
http://www.dotnetcircle.it/bologna05.aspx
AlessandroD
2005-01-25 16:32:36 UTC
Permalink
Post by Luca Bianchi
Post by AlessandroD
select
TESTO,
convert (int,
left (TESTO, isnull (nullif (patindex ('%[^0-9]%', TESTO), 0),
len(TESTO) + 1) - 1)
)
Si può semplificare scrivendo
SELECT LEFT(testo, PATINDEX ('%[^0-9]%', testo) -1)
E nel caso TESTO sia completamente numerico?
Si avrebbe left(TESTO, -1) che però genera un errore, il trigo con isnull e
nullif l'ho messo proprio per risolvere questo caso.
Ciao, Alessandro
Andrea Benedetti
2005-01-25 16:43:40 UTC
Permalink
"AlessandroD" <***@wf.it> wrote
in message news:***@TK2MSFTNGP14.phx.gbl...
[cut]
Post by AlessandroD
E nel caso TESTO sia completamente numerico?
declare @testo varchar(20)
set @testo = '1234'

select
case when isnumeric(@testo) = 1 then @testo
else LEFT(@testo, PATINDEX ('%[^0-9]%', @testo) -1) end as numero


set @testo = '123ww456'

select
Post by AlessandroD
Ciao, Alessandro
Ciao,
Andrea
Albe V°
2005-01-26 08:15:08 UTC
Permalink
Post by AlessandroD
select
Ottima soluzione.

Copioincollo per vostra informazione l'update che per il momento utilizzo,
poi inserirò il Case anche in query, ecc...

update tb_info_aggiuntive
set codice_numerico=cast(
(case
when isnumeric(codice) = 1 then codice
else LEFT(codice, PATINDEX ('%[^0-9]%', codice) -1)
end)
as numeric(18,0))

select codice, codice_numerico
from tb_info_aggiuntive


Ciao

Alberto
--
E tutto mi sembrava andasse bene...
Loading...