Problem z Poleceniem IN MSSQL 2008

0

Witam
Mam pytanie chcę pobrać z bazy danych pozycje które zawierają kilka numerów rejestracyjnych
i mam takie zapytanie
Select * from TekstDok where Tekst IN ('BAUY011','BAU16LP') i to działa zwraca wszystkie wyniki tak jak należy
Lecz z pewnych względów chcę to zrobić na store procedure i robię tak
Create PROC [dbo].[test]
(
@p_numer varchar(100)
)
AS
BEGIN
select * from tekstdok where Tekst in(@p_numer)
END

Jeśli wywołam ja execute test'BAU16LP' to działa ale jeśli dodam drugi numer rejestracyjny

execute test'BAU16LP,BAUY011'
to nie zwraca mi żadnych wyników
Czy ktoś wie gdzie tkwi błąd

0

No chyba dlatego, że procedura wywołuje wówczas takie zapytanie:

select * from tekstdok where Tekst in('BAU16LP,BAUY011')

A chyba nie o to Ci chodziło.

0
somekind napisał(a)

No chyba dlatego, że procedura wywołuje wówczas takie zapytanie:

select * from tekstdok where Tekst in('BAU16LP,BAUY011')

A chyba nie o to Ci chodziło.

Aby zdziałała prcedura musiała by wywołać cos takiego

select * from tekstdok where Tekst in('BAU16LP','BAUY011')

czyli rozdzielić poszczególne pola przecinkiem w w tym momencie procedura w bazie szuka
BAU16LP,BAUY011 takiego stringu i dlatego mi nic nie zwraca

0

dokladnie, ale ms sql sam tego nie zrobi, sam musisz sobie poradzic z jakims podzialem
wygodniej bedzie przekazac te elementy jako jakis prosty xml, bo ms sql fajnie wspiera xquery i daje sporo mozliwosci operacji na xml'ach
wiec do prodedury przekaz string "<nr>BAU16LP</nr><nr>BAUY011</nr>"
pozniej przy uzyciu xquery podziel na rekordy BAU16LP i BAUY011, wynik join'ujesz z tekstdok i pozamiatane

0

Potencjalnym sposobem obejścia problemu jest temporary table...

CREATE PROCEDURE [dbo].[test]
AS
BEGIN
SELECT td.* 
FROM tekstdok td
INNER JOIN #t t ON t.p_numer = td.Tekst;
END;

i wywołanie:

CREATE TABLE #t (p_numer varchar(50));

INSERT INTO #t VALUES ('BAU16LP');
INSERT INTO #t VALUES ('BAUY011');

EXEC dbo.test;
0

o najn!
Adam czemu?
a kiedy ta tabela bedzie zdropowana?
a jak jednoczesnie dwie (lub wiecej) procedur wstawi do niej dane to wyjdzie syf
cos musi jeszcze juz uzyte wartosci usuwac z tej tabeli
poza tym proceduta test zaklada istnienie #t (wiem ze pewnie w przykladzie nie naklepales pelnego rozwiazania, mi tez by sie nie chcialo)

mysle ze xml jest tu bardzo wygodnym wyjsciem, a jego maly rozmiar nie ma znaczenia dla wydajnosci
lub napisanie jakiegos splitera stringa i w konsekwencji odtzymania zmiennej tabelarycznej, ktoa mozemy joinowac z tabela do filtracji
lub dynamiczne budowane zapytanie (ble, nie wiem czemu to napisalem :D)

0
AdamPL napisał(a)

Potencjalnym sposobem obejścia problemu jest temporary table...

CREATE PROCEDURE [dbo].[test]
AS
BEGIN
SELECT td.*
FROM tekstdok td
INNER JOIN #t t ON t.p_numer = td.Tekst;
END;

> i wywołanie:
> <code>
CREATE TABLE #t (p_numer varchar(50));

INSERT INTO #t VALUES ('BAU16LP');
INSERT INTO #t VALUES ('BAUY011');

EXEC dbo.test;

pierwszy raz widzę takie rozwiązanie. W sumie działa
to co tu podałem jest tylko kawałkiem procedury więc teraz spróbuje to teraz zastosować w mojej procedurze

0

Nie miałem wcześniej czasu wyjaśnić wątpliwości massthera dlatego napiszę to teraz korzystając z wolnej chwili. Tabela tempowa (poprzedzona pojedynczym znakiem #) istnieje tylko dla sesji w której została utworzona. Dodatkową zaletą jest to, że można jej użyć w procedurach bez uprzedniej deklaracji, bez create. Tabela przestaje istnieć wraz z końcem sesji. Gdyby dwóch użytkowników wywołało ten kod w tej samej chwili to będą mieli dwie niezależne, niegryzące się kopie tej tabeli.

Tabele tempowe istnieją od wersji MSSQL 2005. Wcześniej również stosowano podobne rozwiązania jednak wtedy taka tabela była zwykłą tabelą z dołączonym SPID-em i trzeba było ją czyścić przed każdym użyciem.

0

od kiedy się dowiedziałem, że w mssql istnieje typ 'tabelowy', przestałem w procedurach używać tempowych tabelek. Wystarczy zadeklarować odpowiednią zmienną i hopsa...

DECLARE @dupa TABLE(p1INT, p2 VARCHAR(256))
INSERT INTO @dupa
SELECT a,b FROM tabela

generalnie zmienną traktujemy jako tabele. Nie wiem dlaczego ludzie masowo w procedurach nie korzystają z tego typu zmiennej :)

... a nawiązując do pytania, można zrobić odpowiednie inserty do zmiennej, a następnie

SELECT * FROM tabela WHERE id IN (SELECT p1 FROM @dupa)
0

@areksum - Table variable o której piszesz w gruncie rzeczy nie różni się zasadniczo od local temporary table (z jednym #). Table variable musi być wcześniej zadeklarowane przed createm procedury, a local temporary table nie. Table variable może być szybsze dla małych porcji danych, z kolei local temporary table lepiej sprawdza się w pozostałych przypadkach. Obie te struktury istnieją tylko w ramach swojej sesji i znikają wraz z jej końcem.

0

musze sie pokajac, moj blad, juz dawno nie uzywalem tabel tymczasowych (ostatnio w ms sql 2000)
sprawdzilem i faktycznie nie ma problemu pomiedzy sesjami w ms sql 2008

result select [name] from tempdb.sys.tables
#tmp1_______________________________________________________________________________________________________________000000000003
#tmp1_______________________________________________________________________________________________________________000000000004

a po zamknieciu connection faktycznie gina te tabele

1 użytkowników online, w tym zalogowanych: 0, gości: 1