|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
[SQL] UNIQUE...
Ciao, a tutti.
sto convertendo alcune tabelle da FoxPro a SQL utilizzando SQL Server. In FoxPro ho un campo che se non è vuoto deve essere univoco*, c'è un modo in SQL per ricreare la stessa situazione? So che utilizzando la clausola UNIQUE non posso avere valori doppi ma questo vale anche se è vuoto. Qualcuno ha qualche idea? Grazie in anticipo. * In foxpro il campo è reso univoco dall'indice, che ha come filtro la condizione !EMPTY(...) per cui è univoco solo se non è vuoto.
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quello che chiedi in SqlServer non si puo' fare in modo naturale perche' NULL e' un valore come un altro, e quindi non si possono inserire piu' NULL nella stessa colonna con vincolo unique.
(PS: Ritengo che il comportamento di altri engine, come ORACLE o appunto FoxPro sia quello corretto). Pero' esiste un workaround: Innanzitutto la tabella deve disporre di una colonna univoca a singola colonna. Quindi o c'e' gia' una chiave primaria/colonna univoca oppure occorre metterla con una IDENTITY(1,1) Chiamiamo COLONNA1 la colonna target, ovvero quella per la quale si vorrebbe il vincolo di univocita' come sotto Oracle, FoxPro, etc. Occorre inserire una nuova colonna calcolata, chiamiamola SURRUK, che varra' COLONNA1 quando COLONNA1 non e' NULL, altrimenti varra' il valore della colonna univoca. Il calcolo e' quindi CASE WHEN COLONNA1 != NULL THEN COLONNA1 ELSE **UK** END Per costruzione, quando si inserira' una riga con null, allora SURRUK conterra' un valore sicuramente univoco. Quando invece si inserira' qualcosa in Colonna1, allora SURRUK varra' tale valore. Su SURRUK si potra' aggiungere un constraint di univocita' che si comportera' proprio come desiderato. Esempio con chiave primaria gia' esistete di tipo numerico, e con colonna target "Colonna1" di tipo testuale Codice:
create table prpr
(
veraPK int identity(1,1),
Colonna1 varchar(30),
SURRUK as CASE WHEN Colonna1 IS NOT NULL THEN Colonna1 ELSE CAST( veraPK AS VARCHAR(30)) END,
)
CREATE UNIQUE INDEX IU_PRPR_SURRUK ON prpr(SURRUK);
insert into prpr(Colonna1) values('abc');
insert into prpr(Colonna1) values('def');
insert into prpr(Colonna1) values(NULL);
insert into prpr(Colonna1) values(NULL);
-- fin qui tutto OK!!!
insert into prpr(Colonna1) values('abc');
-- Qui si schianta.
-- Schiantare e' il verbo tecnico usato in questi casi.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 20-05-2009 alle 17:20. |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
Ok, sembra ottimo adesso provo
Dovrebbe funzionare anche per stringhe vuote che non sono null, vero? Basta cambiare la condizione in Codice:
SURRUK as CASE WHEN Colonna1 IS NOT NULL AND Colonna1 <> '' THEN Colonna1 ELSE CAST( veraPK AS VARCHAR(30)) END, Cmq dire che il foxpro si comporti in modo corretto è bella grossa Ti ringrazio, ciao!
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Si', funziona anche per il nuovo comportamento da te descritto.
Che SQLServer (e altri) si comporti in modo errato e invece Oracle (e FoxPro e altri) invece in modo giusto e' arbitrario, nel senso che l'unica direttiva del SQL e' stata che NULL deve essere trattato come "Assenza di valore". La domanda se su una colonna univoca possano essere presenti piu' record con "Assenza di valore" resta ambigua, e non chiaramente definita dallo stadard. Comunque, per la cronaca, in SQL Server 2008 e' stato aggiunto il concetto di indici e constraint filtrati. Per esempio potrei voler aggiungere un constraint di univocita' su una colonna, valente pero' solo per i valori tra 1000 e 2000. Con questi nuovi oggetti e' quindi possibile descrivere esattamente il comportamento da te desiderato.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
Quote:
Interessante questa nuova caratteristica di SQL Server 2008, purtroppo abbiamo già rimpianto il fatto di non averlo messo come requisito minimo per il nostro programma... ci faciliterebbe di molto il passaggio da Fox a SQL Ti ringrazio ancora per la disponibilità e l'aiuto,
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Peraltro FoxPro non lo conosco neppure tanto bene, l'ho usato solo una volta per lavoro, e non mi sbilancerei con opinioni sul motore. PS: La migrazione da SqlServer2005 a SqlServer2008 e' abbastanza indolore. Rischia addirittura di essere trasparente, a differenza di quella dal 2000 al 2005. Buon lavoro.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
Premettoc he non ho ancora provato, però ci ho pensato un attimo e la cosa ha la limitazione che se inserisco dei numeri la cosa potrebbe non funzionare, o sbaglio?
Per ovviare a questo credo sia: Codice:
SURRUK as CASE WHEN Colonna1 IS NOT NULL THEN CAST( veraPK AS VARCHAR(30)) + Colonna1 ELSE CAST( veraPK AS VARCHAR(60)) END Grazie, Andrea.
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Se invece la colonna originale e' un numero, allora bastera' che anche surruk sia un numero, senza quindi dover castare piu' nulla, e lo statement sarebbe Codice:
SURRUK as CASE WHEN Colonna1 IS NOT NULL THEN Colonna1 ELSE ChiaveUnivoca END Quindi o la chiave primaria e' un numero univoco, e quindi usi quella, oppure aggiungi una colonna di sola lettura ChiaveUnivoca int IDENTITY(1,1) e la usi per questo scopo.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
Se poi Colonna1 fose un numero la cosa sarebbe anche peggio no?
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Propongo, se il dominio di colonna1 fosse solo tra valori positivi, puoi usare -veraPK come valore nel case.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#11 | ||
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
Quote:
E ora che ci penso quanto ho scritto poco fa non funzionerebbe nel senso che farebbe più quello che noi ci proponiamo.... Si fa interessante come problema che dici..? Cmq forse ho capito come fare: Quote:
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
||
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Jul 2008
Città: Solesino (PD)
Messaggi: 1255
|
Provato e sembra funzionare perfettamente!!
Ti ringrazio! Volevo chiederti solo un unica cosa: nel tuo esempio creavi un indice univoco, che differenza c'è tra creare un indice univoco come hai fatto tu e specificare UNIQUE quando dichiaro il campo SURRUK? (mi sembra che venga creato lo stesso, cambia solo che non sono io a decidere il nome dell'indice?) PS: SURRUK ha qualche significato particolare? Ancora grazie
__________________
Desktop: AMD FX-8350 @4,2Ghz + A.C. FREEZER XTREME rev.2 - ASUS M5A99X EVO - 32GB DDR3 (4x8GB) @1866Mhz - Sapphire NITRO+ RX 580 8GB - SSD Crucial MX500 1TB - Antec Two Hundred - Seasonic Focus+ Platinum 650W Always remember to K.I.S.S. |
|
|
|
|
|
#13 | ||
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
E' bene pero' avere il nome a disposizione, nel caso in cui volessero alterare o cancellare (e ci si riferisce per nome) Quote:
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 06:42.




















