In una tabella ho un campo che inizialmente ha valore NULL ma poi, una volta
inserito un valore vorrei che questo valore non sia duplicato:
CREATE TABLE [dbo].[Utenti] (
[ID] [int] NOT NULL ,
[Nome] [char] (25) NOT NULL ,
[Cognome] [char] (25) NOT NULL ,
[UserID] [varchar] (50) NULL ,
[Password] [varchar] (50) NULL
) ON [PRIMARY]
CREATE UNIQUE INDEX [Utenti_IDX]
ON [dbo].[Utenti]([ID]) ON [PRIMARY]
INSERT Utenti (ID, Nome, Cognome)
VALUES (1, 'Esteban', 'Feros')
All'inserimento di un nuovo utente i campi [UserID] e [Password] hanno
valore NULL.
La prima volta che il nuovo utente esegue il login il programma richiede
l'inserimento di un UserID e di una Password per i login futuri. Chiaramente
il login non può essere uguale a quello di un altro utente inserito già
esistente e quindi pensavo di creare un indice sul campo [UserID]:
CREATE UNIQUE INDEX [Utenti_IDX2]
ON [dbo].[Utenti]([UserID]) ON [PRIMARY]
Il problema però è che aggiungendo un nuovo utente prima che l'ultimo utente
inserito abbia aggiornato il suo UserID:
INSERT Utenti (ID, Nome, Cognome)
VALUES (2, 'Etienne', 'Rouge')
mi viene segnalato l'errore che non è possibile aggiungere un nuovo record
in base all'indice Utenti_IDX2.
Certo, magari potrei fare a meno dell'indice ed ogni volta che un utente
vuole inserire / cambiare il proprio UserID potrei cercare nella tabella se
esiste già un utente con lo stesso UserID, però pensavo di poterlo fare con
un indice.
Avete da suggerirmi qualche soluzione?
Grazie!
--
3st3b4n
www.seber.it
Questo post è stato scritto con bit riciclati
personalmente aggiungerei anche ID alla definizione dell'indice,
CREATE UNIQUE INDEX [IX_utenti_UserId_Password] ON [dbo].[Utenti]
( [ID] , [UserID] , [Password] )
ON [PRIMARY]
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
Un indice UNIQUE consente la presenza di un valore NULL (a differenza del
vincolo PK che non lo consente) ma può essere presente UN solo valore NULL
(e filosoficamente ci sarebbe da discutere), quindi è da escludersi questa
strada. In ogni caso la presenza di un indice (non unique) sul campo
faciliterebbe la ricerca di un eventuale valore duplicato eseguendo il
controllo nel momento in cui l'utente si registra. L'alternativa che mi
viene in mente è quella di inserire il record (quindi comprensivo di Nome e
Cognome) nel momento in cui effettua il primo logon oppure, in alternativa,
memorizzare le informazioni anagrafiche (Nome e Cognome) in una tabella e
quelle per l'accesso (UID e PWD) in un'altra relazionate per mezzo dell'ID.
Ad ogni modo mi viene da pensare che per poter informare l'utente che esiste
già un altro utente con la stessa UserID, devi comunque intercettare,
dall'applicazione, il codice di errore di chiave duplicata; a questo punto
sarebbe altrettanto agevole eseguire l'inserimento per mezzo di una stored
procedure che esegua il controllo di esistenza. Sto pensando ad una stored
procedure simile a
==========================
CREATE PROC dbo.FirstAccess
@id SMALLINT,
@uid VARCHAR(20),
@pwd VARCHAR(20)
AS
IF EXISTS (SELECT 1 FROM dbo.Utenti WHERE UserID = @uid)
RETURN -1
UPDATE dbo.Utenti
SET UserID = @uid,
Password = @pwd
WHERE ID = @id
RETURN 0
==========================
Testando quindi il valore di uscita della stored procedure puoi informare
l'utente che lo userid esiste già oppure che è stato accettato
> Grazie!
Bye
--
Luca Bianchi
Microsoft MVP - SQL Server
http://mvp.support.microsoft.com
puoi creare un vincolo di univocità su un sottoinsieme della tabella
sfruttando le viste indicizzate, per esempio una cosa del tipo
create table Utenti(id int identity,nome varchar(50), username
varchar(50), password varchar(50))
go
create view vi_Utenti with schemabinding
as
select username from dbo.utenti where not username is null
go
create unique clustered index IC on vi_Utenti(username)
go
drop view vi_Utenti
drop table Utenti
marc.
3st3b4n ha scritto:
> salve,
> 3st3b4n wrote:
>> Ciao a tutti!
>>
>> In una tabella ho un campo che inizialmente ha valore NULL ma poi,
>> una volta inserito un valore vorrei che questo valore non sia
>> duplicato:
>>
>> CREATE TABLE [dbo].[Utenti] (
>> [ID] [int] NOT NULL ,
>> [Nome] [char] (25) NOT NULL ,
>> [Cognome] [char] (25) NOT NULL ,
>> [UserID] [varchar] (50) NULL ,
>> [Password] [varchar] (50) NULL
>> ) ON [PRIMARY]
>> ...
>
> personalmente aggiungerei anche ID alla definizione dell'indice,
> CREATE UNIQUE INDEX [IX_utenti_UserId_Password] ON [dbo].[Utenti]
> ( [ID] , [UserID] , [Password] )
> ON [PRIMARY]
Intanto non metterei l'indice sulla password: non mi interessa se più di un
utente usa la stessa password. E poi che me ne faccio dell'indice sul campo
ID? Quello è sempre diverso e quindi due utenti che decidessero di usare la
stessa parola come UserID come farei a distinguerli al momento del login?
l'aggiunta della colonna [ID] consente di mantenere l'unicita' anche a
livello di NULL sugli altri 2 attributi (NULL al momento della generazione)
della riga.. e giustamente e' sempre diverso in quanto unico per ogni
utente...ma giustamente ti complichi la vita nella gestione dell'unicita'
del binomio userid/password
per la validazione sull'unicita' della sola UserID, mantenendo il disegno
attuale, devi invece procedere come indicato da Luca.. in effetti la sua
soluzione di inserire un valore di default derivante dalle altre colonne del
predicato .. e meglio ancora avere una relazione separata..
>> Avete da suggerirmi qualche soluzione?
>
Ho optato per questa soluzione. Grazie per il suggerimento.