Anomalie con il like

venerdì 27 ottobre 2006 - 17.26

trinity Profilo | Guru

ragazzi,
scusate una info..perchè se eseguo una select al cui interno vi è una like e il dato anche se non lo passo, quando esegue l'istruzione mi prende il primo dato della tabella..vi faccio un esempio e vi posta il codice che ho scritto

stored che eseguo:

ALTER PROCEDURE [dbo].[GetComune] ( @Comune Varchar(250) ) AS BEGIN Select codcomune,comune,prov From dbo.Comuni Where comune LIKE @Comune +'%' END



Il codice sorgente non è stato renderizzato quiperchè non c'è sufficiente spazio.Clicca qui per visualizzarlo in una nuova finestra
se non valorizzo il parametro @Comune il codice mi restituisce comunque il primo valore della tabella...invece io vorrei che non fosse così, se viene passato un campo vuoto non deve prendere nulla mentre se passo anche una sola lettera allora esegue la ricerca con il like.

Ciao
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/

lbenaglia Profilo | Guru

>se non valorizzo il parametro @Comune il codice mi restituisce
>comunque il primo valore della tabella...invece io vorrei che
>non fosse così, se viene passato un campo vuoto non deve prendere
>nulla mentre se passo anche una sola lettera allora esegue la
>ricerca con il like.

Ciao Fabio,

guarda questo codice:

USE tempdb; GO CREATE PROCEDURE dbo.up_GetContactByLastName( @LastName nvarchar(50) = NULL ) AS SELECT ContactID, FirstName, LastName FROM AdventureWorks.Person.Contact WHERE LastName LIKE @LastName + N'%'; GO DECLARE @LastName nvarchar(50); SET @LastName = NULL; EXEC dbo.up_GetContactByLastName; /* Output: ContactID FirstName LastName ----------- ---------- ------------ (0 row(s) affected) */ SET @LastName = N'Man'; EXEC dbo.up_GetContactByLastName @LastName; GO /* Output: ContactID FirstName LastName ----------- ---------- ------------ 546 Ajay Manchepalli 547 Parul Manek 548 Tomas Manzanares (3 row(s) affected) */ DROP PROCEDURE dbo.up_GetContactByLastName;

Se provi a togliere il valore di default del parametro @LastName nella definizione della stored procedure, quando andrai ad eseguirla otterrai l'errore:

Msg 201, Level 16, State 4, Procedure up_GetContactByLastName, Line 0
Procedure or Function 'up_GetContactByLastName' expects parameter '@LastName', which was not supplied.

Nel tuo caso invece ottieni comunque un risultato, quindi significa che lato client passi ugualmente un valore a quel parametro... forse una stringa nulla?

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

trinity Profilo | Guru

si in effetti ci passa una stringa nulla

ma il tuo esempio può andar bene per me?

comunque il declare a cosa serve in questo caso e la N prima del '%'?

ciao Lorenzo e grazie sei sempre mitico
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/

lbenaglia Profilo | Guru

>si in effetti ci passa una stringa nulla
Ecco
Guarda che succede se non setti un valore di default per il parametro:

USE tempdb; GO CREATE PROCEDURE dbo.up_GetContactByLastName( @LastName nvarchar(50) = NULL ) AS SELECT ContactID, FirstName, LastName FROM AdventureWorks.Person.Contact WHERE LastName LIKE @LastName + N'%'; GO CREATE PROCEDURE dbo.up_GetContactByLastNameWithoutDefault( @LastName nvarchar(50) ) AS SELECT ContactID, FirstName, LastName FROM AdventureWorks.Person.Contact WHERE LastName LIKE @LastName + N'%'; GO DECLARE @LastName nvarchar(50); SET @LastName = N''; EXEC dbo.up_GetContactByLastName; /* Output: ContactID FirstName LastName ----------- ---------- ------------ (0 row(s) affected) */ EXEC dbo.up_GetContactByLastNameWithoutDefault @LastName; GO /* Output: ContactID FirstName LastName ----------- ---------- ------------ 1 Gustavo Achong 2 Catherine Abel 3 Kim Abercrombie ... 19975 Crystal He 19976 Crystal Zheng 19977 Crystal Hu (19972 row(s) affected) */ DROP PROCEDURE dbo.up_GetContactByLastName, dbo.up_GetContactByLastNameWithoutDefault;

>ma il tuo esempio può andar bene per me?
Direi di si

>comunque il declare a cosa serve in questo caso e la N prima
>del '%'?
Dato che il data type della colonna LastName è unicode (nvarchar(50)), sia il parametro che il suo valore sono definiti anch'essi come unicode (quindi metto la N'...' che sta per National Language nello standard ANSI SQL-92) in modo da evitare inutili cast impliciti da ANSI a UNICODE.

Come sempre maggiori dettagli sui BOL:

"Constants (Transact-SQL)"
http://msdn2.microsoft.com/en-us/library/ms179899.aspx

>ciao Lorenzo e grazie sei sempre mitico
Oh già...

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

trinity Profilo | Guru

Lorenzo ancora non mi funziona...
ti posto il codice così ti faccio capire come il programma lavora...

prima di tutto ho corretto la stored come mi hai detto tu:

ALTER PROCEDURE [dbo].[GetComune] ( @Comune Varchar(250)=NULL ) AS BEGIN Select codcomune,comune,prov From dbo.Comuni Where comune LIKE @Comune + N'%' END

poi ecco la classe che richiamo nel compilatore:

Public Class GestoreComune Public Function CaricaRec(ByVal ObjComune As PropertyComune) As PropertyComune Dim oComune As PropertyComune = New PropertyComune Try SqlCmd.CommandText = "GetComune" SqlCmd.Parameters.Add("@Comune", SqlDbType.VarChar).Value = ObjComune.Comune SqlCmd.Connection = Db SqlCmd.CommandType = CommandType.StoredProcedure SqlDr = SqlCmd.ExecuteReader If SqlDr.Read() Then oComune.CodiceComune = SqlDr.GetSqlInt32(0).Value() oComune.Comune = SqlDr.GetSqlString(1).Value oComune.Provincia = SqlDr.GetSqlString(2).Value End If Return oComune Catch ex As Exception Throw ex Finally SqlDr.Close() SqlCmd.Parameters.Clear() SqlCmd.Dispose() End Try End Function

nella form ecco cosa vado a scrivere

Private Sub TextBox7_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox7.KeyUp
caricacomune(Me.TextBox7.Text)
End Sub

questa è la routine che richiama la classe e valorizza le text

Private Sub caricacomune(ByVal comune As String) ObjComune.Comune = comune oComune = Read_record_Com.CaricaRec(ObjComune) If IsNothing(oComune.Comune) = False Then Me.TextBox7.Text = oComune.Comune Me.TextBox8.Text = oComune.Provincia Me.Label12.Text = CStr(oComune.CodiceComune) End If End Sub

ho utilizzato il debug e ho visto che appena il focus passa sulla textbox il valore che passo al parametro è: "" solo che così facendo nella textbox viene visualizzato il primo record della tabella comuni in ordine alfabetico...


Spero che ti ho fatto vedere tutto

Ciao e grazie

Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/

lbenaglia Profilo | Guru

>prima di tutto ho corretto la stored come mi hai detto tu:
>
>ALTER PROCEDURE [dbo].[GetComune]
>(
>@Comune Varchar(250)=NULL
>)
>AS
>BEGIN
>Select codcomune,comune,prov
>From dbo.Comuni Where comune LIKE
>@Comune + N'%'
>END

Fermo. @Comune è varchar, la colonna comune non ne ho idea, per quale motivo hai scritto + N'%' ??
Se la colonna comune è unicode allora deve esserlo anche il parametro @Comune, se invece è ansi allora togli quella N!!

>ho utilizzato il debug e ho visto che appena il focus passa sulla
>textbox il valore che passo al parametro è: "" solo che così
>facendo nella textbox viene visualizzato il primo record della
>tabella comuni in ordine alfabetico...

Non so che dirti, il mio esempio hai visto che funziona lato SQL Server.
Ora se hai problemi con .NET posta sul forum opportuno.

>Ciao e grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

lbenaglia Profilo | Guru

>Lorenzo ancora non mi funziona...

No, aspetta, ho fatto una scemata
Nel post di ieri non so come mai, mi sono dimenticato di specificare il parametro di input nella chiamata della stored procedure up_GetContactByLastName:

DECLARE @LastName nvarchar(50); SET @LastName = N''; EXEC dbo.up_GetContactByLastName @LastName; GO /* Output: ContactID FirstName LastName ----------- ---------- ------------ 546 Ajay Manchepalli 547 Parul Manek 548 Tomas Manzanares (3 row(s) affected) */ DROP PROCEDURE dbo.up_GetContactByLastName;

Ed è ovvio che funzioni in questo modo!
Per risolvere il problema (questa volta sul serio ) puoi fare così:

USE tempdb; GO CREATE PROCEDURE dbo.up_GetContactByLastName( @LastName nvarchar(50) = NULL ) AS IF @LastName IS NULL OR LEN(@LastName) = 0 SELECT ContactID, FirstName, LastName FROM AdventureWorks.Person.Contact WHERE 1 = 0; ELSE SELECT ContactID, FirstName, LastName FROM AdventureWorks.Person.Contact WHERE LastName LIKE @LastName + N'%'; GO DECLARE @LastName nvarchar(50); SET @LastName = N''; EXEC dbo.up_GetContactByLastName @LastName; EXEC dbo.up_GetContactByLastName NULL; EXEC dbo.up_GetContactByLastName; /* Output: ContactID FirstName LastName ----------- ---------- ------------ (0 row(s) affected) */ SET @LastName = N'Man'; EXEC dbo.up_GetContactByLastName @LastName; GO /* Output: ContactID FirstName LastName ----------- ---------- ------------ 546 Ajay Manchepalli 547 Parul Manek 548 Tomas Manzanares (3 row(s) affected) */ DROP PROCEDURE dbo.up_GetContactByLastName;

>Ciao e grazie
Scusami ancora per la cavolata che ho scritto

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

trinity Profilo | Guru

FUNZIONA!!!!
ti ringrazio mille Lorenzo sei un mito...

solo una piccola informazione perchè nella stored di esempio che mi hai passato e precisamente nella if hai messo Where 1=0? così:
IF @LastName IS NULL OR LEN(@LastName) = 0
SELECT ContactID, FirstName, LastName
FROM AdventureWorks.Person.Contact
WHERE 1 = 0; ------> cosa significa?
ELSE
SELECT ContactID, FirstName, LastName
FROM AdventureWorks.Person.Contact
WHERE LastName LIKE @LastName + N'%';

potevo anche mettere LIKE @LastName + N'' per esempio?

Ciao
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/

lbenaglia Profilo | Guru

> WHERE 1 = 0; ------> cosa significa?

Ti permette di ottenere io output un result set di 0 righe (la condizione 1 = 0 è sempre falsa) ma con i nomi delle colonne ed i data type della tabella base.

> WHERE LastName LIKE @LastName + N'%';
>
>potevo anche mettere LIKE @LastName + N'' per esempio?
No. Concatenare una stringa nulla ad un parametro stringa non serve a niente. Inoltre non ha senso utilizzare l'operatore LIKE per verificare l'uguaglianza con un a stringa... a questo punto utilizza l'operatore =.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5