Trick (?) z processing-instruction()

Całkiem niedawno szukając materiałów na temat przetwarzania XML znalazłem opis pewnego tricku: jeśli chcesz ładnie wyświetlić wielolinijkowy tekst wyświetlany w SSMS w siatce wyników – zastosuj taki kawałek kodu:

SELECT SomeCol AS 'processing-instruction(q)'
FROM Whatever
FOR XML PATH(''), TYPE

I tyle. Akurat ten fragment pochodzi ze strony Davida Wentzela, ale widziałem go u kilku innych osób.

No super, ale dlaczego tak i co to w ogóle oznacza? Czemu działa? I co pokazuje?
Czytaj dalej

Reklamy

SNAPSHOT vs READ COMMITTED

We wrześniu prowadziłem krótki warsztat SQL. Podczas poruszania tematu poziomów izolacji transakcji padło pytanie, na które nie potrafiłem udzielić odpowiedzi. Chodziło o interakcję dwóch poziomów izolacji: SNAPSHOT i READ COMMITTED, a ja z trybem SNAPSHOT miałem do czynienia głównie w książkach i niestety nie pamiętałem dokładnie co się stanie.

„Załóżmy, że mamy dwie sesje o poziomach izolacji SNAPSHOT i READ COMMITTED, które operują na tym samym zbiorze danych. Sesja nr 1 (SNAPSHOT) odczytuje dane, w tym czasie sesja nr 2 (READ COMMITTED) aktualizuje dane – np jeden rekord. Po tej aktualizacji sesja nr 1 chce usunąć rekord zaktualizowany w sesji nr 2. Co się stanie? Jaki będzie wynik?”

Przeprowadźmy test. Zakładam nową bazę, w której włączam obsługę trybu SNAPSHOT oraz tabelę, w której będę modyfikował jeden rekord. Czytaj dalej

87. Spotkanie PLSSUG – dodatek o FILESTREAM

7 maja 2015 roku na 87. spotkaniu warszawskiej grupy PLSSUG prowadziłem sesję nt. FILESTREAM w SQL Server. Zostały dwa pytania, na które chciałbym uzupełnić odpowiedź.

1. Czy można utworzyć grupę plików zawierającą FILESTREAM na zasobie sieciowym?

W pierwszej chwili odpowiedziałem, że nie – z tego co wiem, nie można założyć grupy FILESTREAM na zasobie sieciowym – musi być bezpośrednio na dysku. Swoją wiedzę opierałem na dokumencie Paula Randalla nt. FILESTREAM oraz jego wpisie na blogu, który ponownie mówi o tym, że reguły tworzenia grup plików pod FILESTREAM maja takie same zasady, jak tworzenie plików baz danych i logów. Przed sesją nie sprawdziłem tego dokładnie, ale kiedy na sesji padło pytanie przypomniałem sobie, że informacje od Paula Randalla pochodzą z 2008 i 2010 roku, a SQL Server 2012 wprowadził możliwość tworzenia plików na zasobach sieciowych. Ale o tym, że jest adnotacja „Filestream is currently not supported on an SMB file share.” już nie pamiętałem – stąd moje zawahanie i stwierdzenie, że się nie da, ale jeszcze sprawdzę.
Czytaj dalej

SQL w SAS – ograniczanie listy obserwacji

Jednym ze sposobów uruchomienia kodu SQL w SAS jest wykonanie PROC SQL. Np.

proc sql;
SELECT *
FROM SASHELP.CLASS
;
quit;

W celu ograniczenia liczby przetwarzanych lub wyświetlanych rekordów możemy zastosować opcje PROC SQL. I tak:

  • INOBS mówi ile obserwacji z każdego zbioru wymienionego w SQL należy wziąć do przetwarzania (odpowiednik TOP/LIMIT użytego w podzapytaniu)
  • OUTOBS mówi ile obserwacji pokazać na koniec przetwarzania (odpowiednik TOP/LIMIT w głównym zapytaniu)

Tak pobierzemy trzy wiersze ze zbioru wynikowego:

proc sql outobs=3;
SELECT *
FROM SASHELP.CLASS
;
quit;

Wszystko fajnie, tylko co jeśli nie chcemy albo nie możemy używać opcji PROC SQL (bo np. piszemy własne oprogramowanie wykorzystując SAS Integration Technologies)? Wówczas mamy dwie możliwości, w zależności od skomplikowania zapytania.

W najprostszym przypadku, jeśli potrzebujemy odpowiednik „SELECT TOP 100 * FROM tabela” wystarczy dodać klauzulę OBS=100 po FROM – zadziała to tak samo jak INOBS. Uwaga – jeśli stosujemy aliasy tabel, to klauzulę należy dodać przed nimi, np.

SELECT * FROM SASHELP.CLASS (OBS=100) sc

Jeśli potrzebujemy ograniczyć listę wynikową, to można ponumerować wiersze za pomocą nieudokumentowanej funkcji MONOTONIC() (której na dodatek SAS nie wspiera)

SELECT * FROM SASHELP.CLASS sc WHERE MONOTONIC() <= 3

Jeśli łączymy się do zbiorów w zewnętrznych bazach danych możemy też zastosować mechanizm SQL Pass-through. Dzięki niemu możemy wykorzystać dialekt SQL wykorzystywany w danym środowisku, a dodatkowo zrzucimy przetwarzanie na bazę danych, a nie na SAS. Więcej o SQL Passthrough np. tutaj lub tutaj.

SQL Server: Jak szybko sprawdzić rozmiary tabel w bazie

CREATE TABLE #rozmiary (
	_name varchar(128),
	_rows int,
	_reserved varchar(18),
	_data varchar(18),
	_index_size varchar(18),
	_unused varchar(18)
)

INSERT INTO #rozmiary exec sp_MSforeachtable "sp_spaceused [?]"

SELECT * FROM #rozmiary ORDER BY _rows DESC

DROP TABLE #rozmiary

Wada – nie podaje przestrzeni nazw w kolumnie _name. Dokumentacja zaleca w takich wypadkach stosowanie sys.dm_db_partition_stats lub sys.dm_db_index_physical_stats

SQL Server 2008 – dodaj grupę lokalną jako login

Przy zarządzaniu dostępami do SQL Servera możemy dodać grupę użytkowników jako jeden login. Potem ułatwia to zarządzanie – zamiast tworzyć i kasować dostęp do serwera i bazy dla każdego nowego użytkownika wystarczy go dodać lub usunąć z grupy. Jak to się robi – na przykładzie ustawienia lokalnej grupy administratorów serwera jako sysadminów SQL Servera:

USE [master]
GO
CREATE LOGIN [NAZWA_SERWERA\Administrators]
FROM WINDOWS
WITH DEFAULT_DATABASE=[master]
GO

EXEC master..sp_addsrvrolemember
@loginame = N'NAZWA_SERWERA\Administrators',
@rolename = N'sysadmin'
GO

Uruchomienie takich poleceń wygeneruje błąd:

Msg 15401, Level 16, State 1, Line 1
Windows NT user or group 'NAZWA_SERWERA\Administrators' not found. Check the name again.
Msg 15007, Level 16, State 1, Procedure sp_addsrvrolemember, Line 68
'NAZWA_SERWERA\Administrators' is not a valid login or you do not have permission.

Okazuje się, że jeśli chcemy dodać grupę lokalną musimy zamiast nazwy serwera użyć BUILTIN:

USE [master]
GO
CREATE LOGIN [BUILTIN\Administrators]
FROM WINDOWS
WITH DEFAULT_DATABASE=[master]
GO

EXEC master..sp_addsrvrolemember
@loginame = N'BUILTIN\Administrators',
@rolename = N'sysadmin'
GO

I działa.

Case sensitive REPLACE

Kolejne pytanie: jak wykonać REPLACE w SQL Serverze, ale tak żeby zamieniało będąc wrażliwym na wielkość znaków? Czyli coś w stylu:

REPLACE(kolumna, ‚mars’, ‚Snickers’) – źle
REPLACE(kolumna, ‚Mars’, ‚Snickers’) – dobrze

Funkcja REPLACE dokonuje porównania stringów na podstawie parametru COLLATION bazy danych lub kolumny. Aby zmienić to zachowanie najprościej lokalnie wykorzystać COLLATE.
Czytaj dalej