Dziś krótko o pewnym problemie, który jest wydaje się dość powszechny. Tytuł posta dla niektórych czytelników może wyglądać znajomo ponieważ to jest komunikat błędu, z którym można się spotkać podczas pracy z SQL Serverem. Co on oznacza i kiedy można na niego trafić?
Pełna treść komunikatu jest następująca:
Invalid use of a side-effecting operator ‘nazwa operatora’ within a function.
Oznacza to tyle, że wewnątrz funkcji próbujemy użyć operatora, który może mieć potencjalny wpływ na bazę danych. Jako efekt uboczny traktuje się np. modyfikacje danych, czy zmiana stanu bazy. Funkcje w SQL Server z założenia nie mogą modyfikować danych (chociaż istnieją jakieś dziwaczne sztuczki), a jedynie transformować je do innej postaci.
Ja osobiście spotkałem się z tytułowym problemem przy okazji dwóch operatorów:
EXEC
OPEN SYMMETRIC KEY
O ile pierwszy przypadek jest raczej oczywisty (w procedurach składowanych możemy modyfikować dane bazie więc SQL Server traktuje je z góry jako side-effecting), o tyle drugi przypadek nie jest oczywisty na pierwszy rzut oka.
Co mówi dokumentacja na temat na temat operatora OPEN SYMMETRIC KEY
?
Decrypts a symmetric key and makes it available for use.
“Deszyfruje klucz i pozwala z niego korzystać”, czyli w zasadzie nic więcej, na co byśmy sami wpadli. Dalej w dokumentacji znajduje się fragment, który wyjaśnia (nie wprost) przyczynę tytułowego problemu:
Open symmetric keys are bound to the session not to the security context. An open key will continue to be available until it is either explicitly closed or the session is terminated. If you open a symmetric key and then switch context, the key will remain open and be available in the impersonated context.
Na podstawie powyższego fragmentu dochodzimy do tego, że SQL Server traktuje próbę wywołania komendy OPEN SYMMETRIC KEY
wewnątrz funkcji jako rzecz niedopuszczalną. Wynika to stąd, że otwarcie klucza zmienia również stan bazy w obrębie bieżącej sesji. Biorąc pod uwagę cechy context switching oraz context impersonation w trakcie wykonywania funkcji moglibyśmy np. nieświadomie udostępnić otwarty klucz tam, gdzie niekoniecznie byśmy tego chcieli. Takie zachowanie jest sprzeczne z założem dot. funkcji w SQL Serverze: User-defined functions cannot be used to perform actions that modify the database state.