2016-04-08 52 views
10

To jest proste pytanie i nie mogę wymyślić rozwiązania.Procedura składowana SQL LIKE

mam to zdefiniowane w moim przechowywanej procedury:

@communityDesc varchar(255) = NULL 

@communityDesc jest "aaa, bbb, ccc"

iw moim rzeczywistego zapytania Próbuję użyć IN

WHERE AREA IN (@communityDesc) 

ale to nie zadziała, ponieważ moje przecinki są w ciągu znaków, a nie w ten sposób "aaa", "bbb", "ccc"

Moje pytanie brzmi: czy jest coś, co mogę zrobić dla @communityDesc, więc będzie działać z moją instrukcją IN, na przykład sformatować ciąg znaków?

+0

Czy robisz to po prostu w SQL, czy próbujesz skopiować to, co [parametry wycenione tabelą] (https://msdn.microsoft.com/en-us/library/bb675163.aspx) zostały dodane, aby to osiągnąć? –

+4

Którego DBMS używasz? –

+0

** [Sparametryzuj klauzulę SQL IN] (http://stackoverflow.com/questions/337704/parameterize-an-sql-in-clause) ** – lad2025

Odpowiedz

2

w pierwszym najbardziej utworzyć funkcję podzielić String pewne rzeczy jak ten kod

CREATE FUNCTION dbo.splitstring (@stringToSplit VARCHAR(MAX)) 
RETURNS 
@returnList TABLE ([Name] [nvarchar] (500)) 
AS 
BEGIN 

DECLARE @name NVARCHAR(255) 
DECLARE @pos INT 

WHILE CHARINDEX(',', @stringToSplit) > 0 
BEGIN 
    SELECT @pos = CHARINDEX(',', @stringToSplit) 
    SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1) 

    INSERT INTO @returnList 
    SELECT @name 

    SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)[email protected]) 
END 

INSERT INTO @returnList 
SELECT @stringToSplit 

RETURN 
END 

Następnie można użyć tej funkcji jest zapytanie jak to

WHERE AREA IN (dbo.splitstring(@communityDesc)) 
+0

Czy jest to funkcja typu Inline o wartości tabelarycznej, funkcja o wielu tabelach o wartości tabelarycznej lub funkcja o wartościach szacunkowych? – user979331

+0

Utworzono funkcję, ale dostałem ten błąd ''splitstring' nie jest rozpoznaną wbudowaną nazwą funkcji." – user979331

2

Można to zrobić, dzieląc łańcuch za pomocą funkcji podziału podanej pod here. Funkcja zwraca tabelę z jedną kolumną, która przechowuje twoje tokeny (np. "Aaa", "bbb" ...).

Zapytanie powinna wyglądać następująco:

-- get the splits 
SELECT Name INTO #someTemp 
FROM dbo.splitstring(@communityDesc) 

-- get data where area in within description 
SELECT 1 
FROM yourTable T 
WHERE EXISTS (SELECT 1 FROM #someTemp tmp WHERE T.Area = tmp.Name) 
+0

Otrzymuję dwa błędy, Niepoprawna nazwa kolumny "Nazwa" i Nieprawidłowy obiekt name 'dbo.splitstring' – user979331

+0

Uruchom funkcję 'dbo.splitstring' z podanego linku, aby mieć swoją funkcję w bazie danych. – Alexei

3

In działa tylko z zestawów wartości, a nie ze znaków w ciąg. Aby technicznie odpowiedzieć na twoje pytanie, jedynym sposobem, w jaki możesz to zrobić, jest utworzenie zestawu wartości reprezentujących trzy wartości "aaa", "bbb" & "ccc", a następnie umieszczenie tych trzech wartości w tabeli (tabela lub tabela Temp. zmienna (SQL Server), a następnie wykonaj IN wobec tego zbioru wartości (przed tabelą:

declare @Vals table (value varchar(20)) 
insert @vals(Value) Values('aaa') 
insert @vals(Value) Values('bbb') 
insert @vals(Value) Values('ccc') 

select * from SomeOtherTable 
Where SomeColumn IN (Select value from @vals) 

aby utworzyć zestaw będzie trzeba utworzyć pusty temp tabeli lub zmiennej tabeli trzymać ten zestaw wartości , przeanalizuj ciąg rozdzielany przecinkami na poszczególne wartości i wprowadź te indywidualne wartości do zmiennej tabeli lub tabeli:

Mimo że nie mówisz, jeśli używasz programu SQL Server, to jest to SQL Server Us er określonej funkcji (UDF), która będzie analizować rozdzielany ciąg i zwraca tablicę z jednym rzędem dla każdej wartości delimted:

przypadku utworzenia UDF, wtedy można wykorzystać go w następujący sposób:

select * from SomeOtherTable 
Where SomeColumn IN 
     (Select sVal from 
      dbo.ParseSTring(@communityDesc, ',')) 

/****** Object: UserDefinedFunction [dbo].[ParseString]  
    Script Date:  4/8/2016 1:53:00 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[ParseString] (@S Text, @delim VarChar(5)) 
Returns @tOut Table 
(ValNum Integer Identity Primary Key, 
sVal VarChar(8000)) 
As 
Begin 
Declare @dLLen TinyInt -- Length of delimiter 
Declare @sWin VarChar(8000)-- Will Contain Window into text string 
Declare @wLen Integer -- Length of Window 
Declare @wLast TinyInt -- Boolean to indicate processing Last Window 
Declare @wPos Integer -- Start Position of Window within Text String 
Declare @sVal VarChar(8000)-- String Data to insert into output Table 
Declare @BtchSiz Integer -- Maximum Size of Window 
Set @BtchSiz = 7900 -- (Reset to smaller values to test routine) 
Declare @dPos Integer -- Position within Window of next Delimiter 
Declare @Strt Integer -- Start Position of each data value in Window 
-- -------------------------------------------------------------- 

-- --------------------------- 
If @delim is Null Set @delim = '|' 
If DataLength(@S) = 0 Or 
    Substring(@S, 1, @BtchSiz) = @delim Return 
-- --------------------------- 
Select @dLLen = Len(@delim), 
    @Strt = 1, @wPos = 1, 
    @sWin = Substring(@S, 1, @BtchSiz) 
Select @wLen = Len(@sWin), 
     @wLast = Case When Len(@sWin) = @BtchSiz 
       Then 0 Else 1 End, 
     @dPos = CharIndex(@delim, @sWin, @Strt) 
-- ---------------------------- 
While @Strt <= @wLen 
    Begin 
    If @dPos = 0 Begin -- No More delimiters in window 
     If @wLast = 1 Set @dPos = @wLen + 1 
     Else Begin 
      Set @wPos = @wPos + @Strt - 1 
      Set @sWin = Substring(@S, @wPos, @BtchSiz) 
       -- ------------------------------------- 
      Select @wLen = Len(@sWin), @Strt = 1, 
      @wLast = Case When Len(@sWin) = @BtchSiz 
       Then 0 Else 1 End, 
             @dPos = CharIndex(@delim, @sWin, 1) 
      If @dPos = 0 Set @dPos = @wLen + 1 
      End 
     End 
     -- ------------------------------- 
    Set @sVal = LTrim(Substring(@sWin, @Strt, @dPos - @Strt)) 
    Insert @tOut (sVal) Values (@sVal) 
    -- ------------------------------- 
    -- Move @Strt to char after last delimiter 
    Set @Strt = @dPos + @dLLen 
    Set @dPos = CharIndex(@delim, @sWin, @Strt) 
    End 
Return 
End 
2

Innym podejściem jest użycie funkcji CHARINDEX(). Jednak użycie funkcji w klauzuli WHERE spowolni działanie.

WHERE CHARINDEX(','+area+',',','[email protected]+',')> 0 

Jeśli pole obszaru składa się zawsze z 3 liter, można to uprościć.

WHERE CHARINDEX(area,@CommunityDec)> 0 

Jest to szybkie rozwiązanie, ale także luka stop. Lepszym rozwiązaniem jest zmiana podejścia do wyszukiwania ciągów w celu utworzenia tabeli z jednym wierszem na kryteria wyszukiwania i użycie zapytania JOIN lub sub zapytania.

5

Ten artykuł może pomóc przez swojego problemu:

http://sqlperformance.com/2012/07/t-sql-queries/split-strings

W tym artykule Aaron Bertrand pisze o swoim problemie. Jest naprawdę długi i bardzo szczegółowy.

One Way byłoby to:

CREATE FUNCTION dbo.SplitStrings_XML 
(
    @List  NVARCHAR(MAX), 
    @Delimiter NVARCHAR(255) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    ( 
     SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)') 
     FROM 
     ( 
     SELECT x = CONVERT(XML, '<i>' 
      + REPLACE(@List, @Delimiter, '</i><i>') 
      + '</i>').query('.') 
    ) AS a CROSS APPLY x.nodes('i') AS y(i) 
    ); 
GO 

Dzięki tej funkcji tylko zadzwonić:

WHERE AREA IN (SELECT Item FROM dbo.SplitStrings_XML(@communityDesc, N',')) 

nadzieję, że może to pomóc.

4

Najprostszym sposobem korzystania z tego zmienna jest:

SELECT * 
FROM something 
WHERE ',' + @communityDesc + ',' Like '%,' + AREA + ',%' 

to dla TSQL do stosowania oracle || t o łączyć łańcuchy

+0

To jest naprawdę fajne !!!! –

1

Możesz po prostu podzielić to csv za pomocą XML i użyć tego do filtrowania w zapytaniu. Nie ma potrzeby używania funkcji zdefiniowanej przez użytkownika lub @Table_Valiable lub #Temp_Table tutaj.

DECLARE @xml as xml,@communityDesc varchar(255) = 'aaa,bbb,ccc' 

SET @xml = cast(('<X>'+replace(@communityDesc,',' ,'</X><X>')+'</X>') as xml) 

SELECT * FROM TABLE1 
WHERE AREA IN (
    SELECT N.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as T(N) 
) 

Jeśli wymagany Ten podział wartości w dalszym procesie, a następnie można wstawić to do #table_Variable lub #Temp_Table i korzystania z nich.

+0

Jeśli te dalsze wartości były wymagane w dalszym procesie, tylko użytkownik może wprowadzić tę wartość do # tabeli_zmiennej lub #Temp_Table i użyć ich, Przykład poniżej, INSERT INTO @Table_variable SELECT N.value (".", "Varchar (10) ") jako wartość FROM @ xml.nodes (" X ") jako T (N) WYBIERZ * Z TABLE1 GDZIE OBSZAR (WYBIERZ Col1 z @ Zmienna_zmienna) –

Powiązane problemy