2010-11-15 12 views
7

Natrafiłem dzisiaj na interesujący problem. Zmieniłem procedurę przechowywaną i umieściłem oświadczenie select na samym końcu. Miało to być tymczasowe i tylko do pracy z danymi. Byłem zaskoczony, gdy dowiedziałem się, że oświadczenie zostało zapisane i było wykonywane za każdym razem, gdy SP działał.Oświadczenia po END w procedurze przechowywanej

SET ANSI_NULLS ON 
GO 

-- Comments usually go here and are saved as part of the SP 
ALTER PROCEDURE [dbo].[MySP] 
    @param INT 
AS 
BEGIN 
    --Your normal SQL statements here 
END 

--You can also add SQL statements here 
select * from LargeTable 

--You have access to the params 
select @param 

To ma sens, że wszystko jest zapisane, nie tylko to, co jest wewnątrz BEGIN/END, inaczej komentarze i SET ANSI_NULLS itp zniknie. Jestem trochę mylić z tym, co zaczyna się tam gdzie, więc mam kilka pytań:

  1. SET ANSI_NULLS zostanie zapisany jako część SP. Potwierdziłem, że każdy SP ma swoją własną wartość. W jaki sposób SQL Server wie o tym, aby zapisać to jako część SP, ponieważ nie zostało wcześniej przywołane? Czy wykonuje pełne skanowanie bieżącego stanu środowiska, a kiedy uruchomi się ALTER PROCEDURE, zapisze stan (prawdopodobnie tylko wartości inne niż domyślne)?
  2. Podobno BEGIN/END są opcjonalne i nie mają żadnego istotnego znaczenia. Dlaczego są one wliczone w cenę? Dają fałszywe poczucie zakresu, który nie istnieje. Wydaje mi się, że nie ma BEGIN/END, a GO na końcu miałoby sens.
+1

BEGIN/END są używane dla zakresu, podobnie jak zawierające wiele instrukcji w IF/WHILE/etc. Szczerze mówiąc, TSQL jest okropny do pracy w porównaniu do PLSQL - który jest znacznie bardziej uporządkowany/zorganizowany w tym, jak używa BEGIN/END, i używa średników do kończenia linii. Podobnie jak TSQL wymaga średnika przed znakiem WITH/CTE, jeśli zadeklarujesz zmienne przed nim ...:/Każdy, kto ma doświadczenie w języku C, może otrzymać PLSQL i być w stanie go przeczytać. Nie mogę tego powiedzieć dla TSQL ... –

+0

@OMG - Więc jaki "zakres" to daje w tym przypadku? Mogę sobie tylko wyobrazić, że jeśli zadeklarujesz zmienną wewnątrz BEGIN/END, nie będzie ona dostępna na zewnątrz. Dlaczego kiedykolwiek wypuścisz instrukcje SQL na zewnątrz? dlaczego nie chcesz umieścić wszystkiego na zewnątrz i bez BEGIN/END? –

+1

Przykład jest ważny, nie powiedziałem, że był mądry;) –

Odpowiedz

5

ANSI NULLS i QUOTED IDENTIFIERS są przechowywane jako atrybuty metadanych kodu procedury składowanej. Można przeglądać te ustawienia poprzez

select * from sys.sql_modules 

Gdy procedura zostanie zapisane, te atrybuty są ustawione na czymkolwiek są do podłączenia za pośrednictwem którego procedura jest zapisywany. Może to prowadzić do irytujących niezgodności, więc bądź ostrożny.

Co do BEGIN/END, to dokładnie tak, jak mówi @bobs - oznaczają one bloki kodu, nie oznaczają początku i końca kodu procedury przechowywanej. (Funkcje, tak, procedury, nie.) Jak mówisz, no BEGIN/END and a GO at the end would make the most sense to sposób, w jaki robię to od lat.

Z technicznego punktu widzenia SQL (próbując) zapisuje wszystko w partii jako część procedury składowanej - czyli cały tekst, który przesyłasz, jako podzielony przez instrukcje GO (jeśli istnieją). Jeśli utkniesz w instrukcji RETURN tuż przed zapytaniami ad hoc, zostaną one uwzględnione w kodzie, ale nigdy nie zostaną uruchomione.

+0

+1 dla' sys.sql_modules' i funkcja ta użyj 'BEGIN/END'. Jedynym problemem z 'GO' na końcu jest to, że nie jest generowany przez opcję modyfikacji, więc następnym razem, gdy go nie ma. Ale nie ma też "BEGIN/END". –

5

Kod BEGIN...END definiuje blok kodu. Nie definiuje początku i końca skryptu ani procedury. Ale, zgadzam się, może to być mylące.

Ustawienia SET QUOTED_IDENTIFIER i SET ANSI_NULLS są zapisane, ale nie inne ustawienia. Sprawdź Interoperability here, aby uzyskać więcej informacji.

+0

To odpowiada na moje pierwsze pytanie, dziękuje: 'Aparat baz danych zapisuje ustawienia zarówno SET QUOTED_IDENTIFIER i SET ANSI_NULLS, gdy procedura Transact-SQL jest tworzona lub modyfikowana ... Inne opcje SET, takie jak USTAW ARITHABORT, ZESTAW ANSI_WARNINGS, lub SET ANSI_PADDINGS nie są zapisywane, gdy procedura jest tworzona lub modyfikowana.Jeśli logika procedury zależy od konkretnego ustawienia, dołącz instrukcję SET na początku procedury, aby zagwarantować odpowiednie ustawienie. " –

1

Otacza serię Transact-SQL sprawozdań tak, że grupa Transact-SQL można stracony. BEGIN i END są słowa kluczowe w języku sterowania.

Kiedy SET ANSI_NULLS jest ON, A SELECT oświadczenie, że korzysta WHERE nazwa_kolumny = NULL zwraca zero wierszy, nawet jeśli istnieją wartości null w column_name. Instrukcja SELECT używająca WHERE nazwa_kolumny <>NULL zwraca zero wierszy, nawet jeśli w kolumnie nazwa_kolumny znajdują się wartości niepuste.

Po wyłączeniu SET ANSI_NULLS, operatory porównania (równe) i nie równe (<>) nie są zgodne ze standardem ISO. Instrukcja SELECT, która używa WHERE nazwa_kolumny = NULL, zwraca wiersze, które mają wartości null w column_name. Instrukcja SELECT używająca WHERE nazwa_kolumny <>NULL zwraca wiersze, które mają niepuste wartości w kolumnie. Ponadto instrukcja SELECT, która używa WHERE nazwa_kolumny <> Wartość XYZ zwraca wszystkie wiersze, które nie są wartością XYZ_ i które nie są NULL.

Gdy SET ANSI_NULLS jest ON, wszystkie porównania z wartością zerową są oceniane jako NIEZNANE. Gdy SET ANSI_NULLS jest OFF, porównanie wszystkich danych z wartością zerową jest oceniane na PRAWDA, jeśli wartość danych wynosi NULL. Jeśli nie podano SET ANSI_NULLS, obowiązuje ustawienie opcji bieżącej bazy danych. Aby uzyskać więcej informacji o opcji bazy danych ANSI_NULLS, zobacz ALTER DATABASE (Transact-SQL) i Ustawianie opcji bazy danych.

SET ANSI_NULLS ON wpływa na porównanie tylko wtedy, gdy jednym z argumentów porównania jest zmienna, która jest NULL lub literalna NULL. Jeśli obie strony porównania to kolumny lub wyrażenia złożone, ustawienie nie ma wpływu na porównanie.

uzyskać skrypt do pracy zgodnie z przeznaczeniem, niezależnie od opcji ANSI_NULLS bazy danych lub ustawienia SET ANSI_NULLS stosuje się NULL i IS NOT NULL w porównaniach, które mogą zawierać wartości null.

SET ANSI_NULLS powinien być ustawiony na WŁĄCZONY w celu wykonywania zapytań rozproszonych.

Ustawienie ANSI_NULLS musi być również WŁĄCZONE podczas tworzenia lub zmieniania indeksów w kolumnach obliczeniowych lub widokach indeksowanych. Jeśli SET ANSI_NULLS jest OFF, wszelkie instrukcje o tabelach z indeksami na kolumnach obliczeniowych lub widokach indeksowanych zakończy się niepowodzeniem. SQL Server zwróci błąd, który wyszczególnia wszystkie opcje SET, które naruszają wymagane wartości. Ponadto po wykonaniu instrukcji SELECT, jeśli SET ANSI_NULLS jest OFF, SQL Server zignoruje wartości indeksu w obliczonych kolumnach lub widokach i rozwiąże operację selekcji tak, jakby nie było takich indeksów w tabelach lub widokach.

+0

Dobre informacje o ANSI_NULLS, ale nie bezpośrednio związane z pytaniem. Nie wiedziałem o zasadach z ostatniego akapitu i zawsze dobrze jest dowiedzieć się więcej. –

Powiązane problemy