2009-08-12 6 views
6

chcę użyć kwerendy jako następujące, szukam dokładnych informacji/link do ucieczki ciągiPrawidłowe String Uciekając się do T-SQL ciąg literały

BOOKTITLE jest NVARCHAR (200)

select * from Books GDZIE BookTitle IN ("Mars i Wenus", "Przepełnienie stosu" \ r \ n ')

Pytanie: Czy tylko "" "trzeba uciec, czy nawet \ r \ n, trzeba również uciec ? MySql .Net Provider udostępnia metodę, aby uciec wartości ciągów, czy istnieje taka funkcja w Sql Server .Net Provider?

Prawdopodobnie potrzebuję ucieczki równoważnej C# dla wartości łańcuchowych.

Jestem świadomy polecenia sparametryzowanego, ale w celu zminimalizowania komunikacji z serwerem do klienta, a moje wartości w klauzuli IN są w liczbie od 20 do 50, to staje się zbyt dużo sieci, aby uruchomić SELECTs dla każdej wartości BookTitle w jednym wywołaniu. Raczej uruchamianie pojedynczego zapytania i zwracanie wszystkich kaskadowanych wyników pomaga w oszczędzaniu zasobów sieciowych.

+0

To komentarz styczny, ale nadal ważny. Jeśli robisz to dla własnych zapytań w studiu zarządzania, w porządku. Ale jeśli robisz to _programmatically_ — budowanie łańcucha zapytania i ucieczkę w programie po stronie klienta —, robisz to źle. Potrzebujesz sparametryzowanej kwerendy. –

+0

Twoja sugestia, że ​​musisz uruchomić 1 wybierz dla każdej wartości parametru jest niepoprawna. Użyj wartościowania tabelarycznego LUB XML LUB użyj łańcucha rozdzielanego przecinkami i rozpakuj go po stronie serwera SQL. To będzie jedno zapytanie. http://www.sommarskog.se/arrays-in-sql-2008.html – Davos

Odpowiedz

2

Są rzeczy, które mają być chronione, niż tylko cytaty i nowego wiersza. Co jeśli jest wejście binarne (przez hakera)? Lepiej używać PreparedStatement (w java) lub jakiegokolwiek innego odpowiednika w języku docelowym. Przykład Java:

PreparedStatement ps = con.prepareStatement("SELECT * FROM Books WHERE BookTitle IN (?, ?)"); 
ps.setString(1, "Mars and Venus"); 
ps.setString(2, "Stack's Overflow 
and 
"); 

ResultSet rs = ps.executeQuery(); 
.... 
+0

Chociaż nie jest to pełna odpowiedź, ale tak, próbowałem podobny rzecz w języku C# z małym obejściem i jego do przyjęcia na razie. –

5

Program SQL Server nie rozpoznaje sekwencji \r\n, niezależnie od tego, czy została zmieniona, czy nie.

Musisz zrobić coś takiego zamiast jeśli chcesz dopasować \r\n w BookTitle:

-- \r = CHAR(13) 
-- \n = CHAR(10) 
SELECT * 
FROM Books 
WHERE BookTitle IN ('Mars and Venus', 'Stack''s Overflow ' + CHAR(13) + CHAR(10)) 
+0

Tak, dostaję to, ale muszę zrobić to w C# dynamicznie dla każdego typu, tak jakbym potrzebował sekwencji ucieczki, której mogę użyć ciąg .replace dla wszystkich takich wartości i przygotować ostateczne zapytanie. –

+0

W takim przypadku nie używaj łańcuchów znaków. Zamiast tego użyj sparametryzowanego zapytania. – LukeH

0

Można użyć parametrów wartości tabeli do przekazania wartości dla instrukcji IN. Jeśli nie używasz wystarczająco nowej wersji Visual Studio i/lub serwera SQL, aby uzyskać dostęp do parametrów wartości tabeli, możesz zamiast tego przekazać jedną listę rozdzielaną przecinkami jako parametr łańcuchowy, a następnie przeanalizować parametr w tabeli. Istnieje kilka metod podziału łańcuchów na zmienną tabela/tabela. Możesz google "podzielić funkcję na serwerze sql" dla kilku opcji.

0

Zazwyczaj co bym zrobiła dla tego typu sytuacjach jest przekazać informacje jako parametr, ale w XML, dzięki czemu można zrobić coś takiego:

DECLARE @iDoc INT 
EXEC sp_xml_preparedocument @iDoc OUTPUT, @MyXml 

SELECT 
    * 
FROM 
    MyTable 
WHERE 
    MyColumn IN (SELECT [Id] FROM OPENXML(@iDoc,'/ss/s',2) WITH ([Id] INT '.')) 

EXEC sp_xml_removedocument @iDoc 

w tym przypadku byłoby xml Wygląda na to, że '<ss><s>1</s><s>2</s>...etc...</ss>'

+0

CRLF nie przeżyłby przetwarzania xml, prawda? Ponieważ jest traktowany jako biały znak, musisz jakoś uciec. Jak w ogóle uciekasz z CRLF w Xml? Zgaduję, że z CDATA, ale jak to by się stało w zapytaniu? – Cyberherbalist

+0

Nie wierzę, że spacje w ogóle muszą zostać usunięte w XML; jest po prostu tym, czym jest – John

2

Wystąpił podobny problem, w którym musiałem mieć IN w moim kwerendzie wybierania, a liczba elementów była zmieniana w czasie wykonywania.

Używam sparametryzowanej kwerendy w postaci procedury przechowywanej i przekazać w ograniczonym ciągu zawierające listę rzeczy, których szukam. Ucieczka jest automatycznie obsługiwana przez system, bez konieczności podejmowania nadzwyczajnych kroków. Lepiej nie ograniczać go znakami, które będą znajdować się w szukanym tekście (np. Przecinkami). pionowy pasek ("|") prawdopodobnie działałby najlepiej w wielu przypadkach. Przy okazji upewnij się, że CRLF w twojej tabeli to CHAR (13) + CHAR (10), ponieważ odwrotnie, nie jest \ r \ n i nie znajdziesz go, jeśli Environment.NewLine był częścią twojego wyszukiwania.

Oto procedura przechowywana przy użyciu rozwiązującego do stołu szybki i brudny parse że użyłem:

CREATE PROCEDURE FindBooks 
(
    @list varchar(500) 
) 
AS 

CREATE TABLE #parse_table (item varchar(500)) 

DECLARE @temp      VARCHAR(500) 
DECLARE @result      VARCHAR(500) 
DECLARE @str      VARCHAR(500) 
DECLARE @pos      SMALLINT 

SET @temp = RTRIM(LTRIM(@list)) 
SET @pos = 1 

WHILE @pos > 0 
    BEGIN 
    SET @pos = CHARINDEX('|',@temp) 
    IF @pos > 0 
     BEGIN 
     SET @result = SUBSTRING(@temp,1,@pos - 1) 
     SET @temp = RTRIM(LTRIM(SUBSTRING(@temp,@pos+1,LEN(@temp) - @pos))) 

     INSERT INTO #parse_table 
    SELECT @result 
     END 
    ELSE 
     INSERT INTO #parse_table 
     SELECT @temp 
END 

SELECT * FROM Books WHERE Title in (select * from #parse_table) 

Wystarczy utworzyć listę tytułów książek jako prosty ciąg (zawierający co wbudowane apostrofy, CRLFs i tak dalej) i użyj sparametryzowanego zapytania. Oczywiście zapisany proces może zawierać inne rzeczy oprócz listy rozdzielanej.

Powiązane problemy