SQL Server

Wirtualna premiera SQL Server 2012

VN:F [1.7.9_1023]
Rating: 5.0/5 (1 vote cast)

Właśnie dowiedziałem się, będąc w Redmond na szkoleniu Bare Metal SQL Server 2012, że 7 marca będzie miała miejsce wirtualna premiera SQL Server 2012! Jeżeli interesuje Cię nowa wersja SQL Servera, chcesz obejrzeć 30+ sesji prowadzonych przez czołowych specjalistów z całego świata i pracowników Microsoft, nie przegap tego wydarzenia i rejestruj się już dzisiaj na witrynie http://www.sqlserverlaunch.com. Na zachętę dodam, że w ramach premiery będzie miał miejsce mały konkurs z ciekawymi nagrodami. Po szczegóły odsyłam już na witrynę wydarzenia. Ja już się zarejestrowałem, a teraz wracam do tworzenia wirtualnych maszyn na potrzeby labów ;-)

Ważne! Wspomniana wirtualna premiera będzie wyłącznie wydarzeniem promującym najnowszą wersję SQL Servera i nie należy jej traktować jako oficjalnej premiery produktu. Nie oczekujcie więc, że 7 marca będziemy w stanie pobrać wersję RTM produktu :-)

Materiały z dwóch edycji SQLDay Workshop

VN:F [1.7.9_1023]
Rating: 5.0/5 (1 vote cast)

Ostatnio informowałem o trzeciej edycji warsztatów SQLDay Workshop. Miejsca na warsztaty rozeszły się błyskawicznie, co tylko potwierdza, jak potrzebne są podobne przedsięwzięcia.

Miło mi poinformować za Tobiaszem Koprowskim, aktualnym prezesem Polskiej Grupy Użytkowników SQL Server (PLSSUG), że na kanale YouTube PLSSUG dostępne są nagrania wideo z dwóch poprzednich edycji warsztatów.

Osoby zainteresowane materiałami zapraszam na podane poniżej strony.

SQLDay Workshop 2009 PlayList: http://www.youtube.com/playlist?list=PL6FF436F4330A598C&feature=plcp

SQLDay Workshop 2010 PlayList: http://www.youtube.com/playlist?list=PLB07B560412F478F6&feature=plcp

Polecam też fanpage PLSSUG na Facebooku, gdzie można śledzić aktualne wydarzenia i działania grupy.

[PL] Nowe obiekty systemowe w SQL Server 2012 RC0

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Całkiem niedawno Aaron Bertrand (SQL Server MVP) opublikował na swoim blogu listę nowych obiektów systemowych, które pojawiły się w SQL Server 2012 RC0, a nie było ich w SQL Server 2012 CTP3. Pomyślałem, że przydałaby się analogiczna lista, ale w odniesieniu do obiektów z SQL Server 2008 R2.

Jak taką listę przyrządzić? W moim przypadku było to dziecinnie proste :-) Mam na jednej maszynie dwie instancje SQL Server – 2012 RC0 i 2008 R2. Wystarczyło na jednej z nich stworzyć serwer dołączony do drugiej i już można było pisać zapytania porównujące metadane obu instancji w stylu:

-- Nowe obiekty
SELECT
	QUOTENAME(SCHEMA_NAME([schema_id])) + '.' +
	QUOTENAME(name) AS object,
	type_desc
FROM sys.system_objects
WHERE is_ms_shipped = 1
EXCEPT
SELECT
	(QUOTENAME(SCHEMA_NAME([schema_id])) + '.' +
	QUOTENAME(name)) COLLATE database_default,
	type_desc COLLATE database_default
FROM [ASUS\SQL2008R2].master.sys.system_objects
WHERE is_ms_shipped = 1
ORDER BY 1;
 
-- Obiekty usunięte
SELECT
	(QUOTENAME(SCHEMA_NAME([schema_id])) + '.' +
	QUOTENAME(name)) COLLATE database_default AS object,
	type_desc COLLATE database_default AS type_desc
FROM [ASUS\SQL2008R2].master.sys.system_objects
WHERE is_ms_shipped = 1
EXCEPT
SELECT
	QUOTENAME(SCHEMA_NAME([schema_id])) + '.' +
	QUOTENAME(name),
	type_desc
FROM sys.system_objects
WHERE is_ms_shipped = 1
ORDER BY 1;

Powyższe zapytania były uruchamiane na instancji SQL Server 2012 RC0, zaś ASUS\SQL2008R2 to nazwa linked servera wskazującego na instancję SQL Server 2008 R2.

Co z tego wyszło?

Nowe obiekty systemowe

Nazwa obiektu Typ obiektu
[INFORMATION_SCHEMA].[SEQUENCES] VIEW
[sys].[availability_databases_cluster] VIEW
[sys].[availability_group_listener_ip_addresses] VIEW
[sys].[availability_group_listeners] VIEW
[sys].[availability_groups] VIEW
[sys].[availability_groups_cluster] VIEW
[sys].[availability_read_only_routing_lists] VIEW
[sys].[availability_replicas] VIEW
[sys].[column_store_dictionaries] VIEW
[sys].[column_store_index_stats] VIEW
[sys].[column_store_segments] VIEW
[sys].[database_filestream_options] VIEW
[sys].[dm_db_database_page_allocations] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_db_fts_index_physical_stats] VIEW
[sys].[dm_db_log_space_usage] VIEW
[sys].[dm_db_objects_disabled_on_compatibility_level_change] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_db_uncontained_entities] VIEW
[sys].[dm_exec_describe_first_result_set] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_exec_describe_first_result_set_for_object] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_filestream_non_transacted_handles] VIEW
[sys].[dm_fts_index_keywords_by_property] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_fts_semantic_similarity_population] VIEW
[sys].[dm_hadr_auto_page_repair] VIEW
[sys].[dm_hadr_availability_group_states] VIEW
[sys].[dm_hadr_availability_replica_cluster_nodes] VIEW
[sys].[dm_hadr_availability_replica_cluster_states] VIEW
[sys].[dm_hadr_availability_replica_states] VIEW
[sys].[dm_hadr_cluster] VIEW
[sys].[dm_hadr_cluster_members] VIEW
[sys].[dm_hadr_cluster_networks] VIEW
[sys].[dm_hadr_database_replica_cluster_states] VIEW
[sys].[dm_hadr_database_replica_states] VIEW
[sys].[dm_hadr_instance_node_map] VIEW
[sys].[dm_hadr_name_id_map] VIEW
[sys].[dm_logconsumer_cachebufferrefs] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_logconsumer_privatecachebuffers] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_logpool_consumers] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_logpool_hashentries] VIEW
[sys].[dm_logpool_sharedcachebuffers] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_logpool_stats] VIEW
[sys].[dm_logpoolmgr_freepools] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_logpoolmgr_respoolsize] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_logpoolmgr_stats] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_os_cluster_properties] VIEW
[sys].[dm_os_memory_broker_clerks] VIEW
[sys].[dm_os_server_diagnostics_log_configurations] VIEW
[sys].[dm_os_volume_stats] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[dm_os_windows_info] VIEW
[sys].[dm_resource_governor_resource_pool_affinity] VIEW
[sys].[dm_server_memory_dumps] VIEW
[sys].[dm_server_registry] VIEW
[sys].[dm_server_services] VIEW
[sys].[dm_tcp_listener_states] VIEW
[sys].[filetable_system_defined_objects] VIEW
[sys].[filetables] VIEW
[sys].[fn_hadr_backup_is_preferred_replica] SQL_SCALAR_FUNCTION
[sys].[fn_MSxe_read_event_stream] SQL_INLINE_TABLE_VALUED_FUNCTION
[sys].[fulltext_semantic_language_statistics_database] VIEW
[sys].[fulltext_semantic_languages] VIEW
[sys].[GeographyCollectionAggregate] AGGREGATE_FUNCTION
[sys].[GeographyConvexHullAggregate] AGGREGATE_FUNCTION
[sys].[GeographyEnvelopeAggregate] AGGREGATE_FUNCTION
[sys].[GeographyUnionAggregate] AGGREGATE_FUNCTION
[sys].[GeometryCollectionAggregate] AGGREGATE_FUNCTION
[sys].[GeometryConvexHullAggregate] AGGREGATE_FUNCTION
[sys].[GeometryEnvelopeAggregate] AGGREGATE_FUNCTION
[sys].[GeometryUnionAggregate] AGGREGATE_FUNCTION
[sys].[registered_search_properties] VIEW
[sys].[registered_search_property_lists] VIEW
[sys].[resource_governor_resource_pool_affinity] VIEW
[sys].[sequences] VIEW
[sys].[sp_audit_write] EXTENDED_STORED_PROCEDURE
[sys].[sp_availability_group_command_internal] EXTENDED_STORED_PROCEDURE
[sys].[sp_begin_parallel_nested_tran] EXTENDED_STORED_PROCEDURE
[sys].[sp_commit_parallel_nested_tran] EXTENDED_STORED_PROCEDURE
[sys].[sp_db_increased_partitions] SQL_STORED_PROCEDURE
[sys].[sp_describe_first_result_set] EXTENDED_STORED_PROCEDURE
[sys].[sp_describe_undeclared_parameters] EXTENDED_STORED_PROCEDURE
[sys].[sp_filestream_force_garbage_collection] SQL_STORED_PROCEDURE
[sys].[sp_filestream_recalculate_container_size] SQL_STORED_PROCEDURE
[sys].[sp_flush_commit_table_on_demand] SQL_STORED_PROCEDURE
[sys].[sp_fulltext_semantic_register_language_statistics_db] SQL_STORED_PROCEDURE
[sys].[sp_fulltext_semantic_unregister_language_statistics_db] SQL_STORED_PROCEDURE
[sys].[sp_get_redirected_publisher] SQL_STORED_PROCEDURE
[sys].[sp_help_spatial_geography_histogram] SQL_STORED_PROCEDURE
[sys].[sp_help_spatial_geometry_histogram] SQL_STORED_PROCEDURE
[sys].[sp_kill_filestream_non_transacted_handles] SQL_STORED_PROCEDURE
[sys].[sp_migrate_user_to_contained] EXTENDED_STORED_PROCEDURE
[sys].[sp_MS_marksystemobject] SQL_STORED_PROCEDURE
[sys].[sp_MScheckIsPubOfSub] SQL_STORED_PROCEDURE
[sys].[sp_MSgetversion] SQL_STORED_PROCEDURE
[sys].[sp_MSsetupnosyncsubwithlsnatdist_cleanup] SQL_STORED_PROCEDURE
[sys].[sp_MSsetupnosyncsubwithlsnatdist_helper] SQL_STORED_PROCEDURE
[sys].[sp_new_parallel_nested_tran_id] EXTENDED_STORED_PROCEDURE
[sys].[sp_redirect_publisher] SQL_STORED_PROCEDURE
[sys].[sp_repl_generateevent] EXTENDED_STORED_PROCEDURE
[sys].[sp_rollback_parallel_nested_tran] EXTENDED_STORED_PROCEDURE
[sys].[sp_sequence_get_range] SQL_STORED_PROCEDURE
[sys].[sp_server_diagnostics] EXTENDED_STORED_PROCEDURE
[sys].[sp_showmemo_xml] EXTENDED_STORED_PROCEDURE
[sys].[sp_validate_redirected_publisher] SQL_STORED_PROCEDURE
[sys].[sp_validate_replica_hosts_as_publishers] SQL_STORED_PROCEDURE
[sys].[trace_xe_action_map] USER_TABLE
[sys].[trace_xe_event_map] USER_TABLE

Kilka obserwacji:

  • pojawiło się ponad 100 nowych obiektów – sporo,
  • wśród nowych obiektów widać sporą grupę funkcji agregujących przeznaczonych do pracy z danymi przestrzennymi,
  • widać pokaźną grupę obiektów zwracających metadane i informacje o HADR,
  • z jakichś powodów nadal dodawane są procedury rozszerzone,
  • kilka obiektów wygląda całkiem ciekawie – np. sp_server_diagnostics.

Obiekty, które były w 2008 R2, ale nie ma ich w SQL Server 2012 RC0

Nazwa obiektu Typ obiektu
[sys].[database_principal_aliases] VIEW
[sys].[sp_ActiveDirectory_Obj] SQL_STORED_PROCEDURE
[sys].[sp_ActiveDirectory_SCP] SQL_STORED_PROCEDURE
[sys].[sp_ActiveDirectory_Start] SQL_STORED_PROCEDURE
[sys].[sp_batch_params] EXTENDED_STORED_PROCEDURE
[sys].[sp_dboption] SQL_STORED_PROCEDURE
[sys].[sp_dropalias] SQL_STORED_PROCEDURE
[sys].[sp_fetchLOBfromcookie] EXTENDED_STORED_PROCEDURE
[sys].[sp_MSgetversion] EXTENDED_STORED_PROCEDURE
[sys].[sp_processmail] SQL_STORED_PROCEDURE
[sys].[xp_adsirequest] EXTENDED_STORED_PROCEDURE
[sys].[xp_deletemail] EXTENDED_STORED_PROCEDURE
[sys].[xp_findnextmsg] EXTENDED_STORED_PROCEDURE
[sys].[xp_get_mapi_default_profile] EXTENDED_STORED_PROCEDURE
[sys].[xp_get_mapi_profiles] EXTENDED_STORED_PROCEDURE
[sys].[xp_MSADEnabled] EXTENDED_STORED_PROCEDURE
[sys].[xp_MSADSIObjReg] EXTENDED_STORED_PROCEDURE
[sys].[xp_MSADSIObjRegDB] EXTENDED_STORED_PROCEDURE
[sys].[xp_MSADSIReg] EXTENDED_STORED_PROCEDURE
[sys].[xp_readmail] EXTENDED_STORED_PROCEDURE
[sys].[xp_sendmail] EXTENDED_STORED_PROCEDURE
[sys].[xp_startmail] EXTENDED_STORED_PROCEDURE
[sys].[xp_stopmail] EXTENDED_STORED_PROCEDURE
[sys].[xp_test_mapi_profile] EXTENDED_STORED_PROCEDURE

Komentarze do listy obiektów usuniętych w porównaniu do wersji 2008 R2:

  • usuniętych zostało sporo procedur rozszerzonych,
  • na liście znalazła się m.in. procedura sp_dboption, którą można było spotkać choćby w skrypcie tworzącym bazę danych Northwind (wiem, wiem, to zabytek, ale niektórzy nadal jej używają do celów edukacyjnych),
  • sporo obiektów dotyczy usługi SQLMail, która została skutecznie zastąpiona usługą Database Mail w poprzednich wersjach SQL Servera.

Zadanie domowe dla chętnych – wyprodukować listy nowych kolumn i kolumn o zmienionych długościach w widokach systemowych w SQL Server 2012 RC0 w porównaniu do wersji 2008 R2. Nie powinno to być wielkie wyzwanie :-) Generalnie, zachęcam do podobnych zabaw, ponieważ w ten sposób odkrywamy nowe obiekty systemowe, poznajemy dogłębnie warstwę metadanych systemu, a to – według mnie – podstawowa wiedza o systemie, dzięki której DBA umie wydobywać stosowne informacje z najgłębszych zakamarków systemu.

[PL] Konferencje, prelekcje, wydarzenia

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Szykuje się sporo atrakcji dla osób zainteresowanych bazami danych, w szczególności tymi implementowanymi w systemie Microsoft SQL Server. Pomyślałem, że dobrze by było zebrać informacje o nadchodzących wydarzeniach i wyostrzyć czujność pasjonatów baz danych.

Już za tydzień, w czwartek 1 grudnia, o godzinie 18:00 w siedzibie firmy Microsoft w Warszawie przy Al. Jerozolimskich 195A rozpocznie się spotkanie warszawskiego oddziału Polskiej Grupy Użytkowników SQL Server (PLSSUG). Z czystym sumieniem polecam obu prelegentów, którzy wystąpią w ramach tego spotkania. Marek Adamczuk, ekspert w dziedzinie architektury rozwiązań i programowania w języku T-SQL, opowie o kursorach – często znienawidzonym i jeszcze częściej niedocenianym elemencie języka T-SQL. Z kolei Włodek Bielski, znakomity specjalista z zakresu hurtowni danych i Business Intelligence, zaprezentuje PowerView – nowe narzędzie do prezentacji danych dostępne w SQL Server 2012. Naprawdę polecam obie ciekawie zapowiadające się sesje i obu prelegentów, których mam przyjemność znać osobiście i z którymi mam lub miałem okazję blisko współpracować.

Jeśli ktoś jest zainteresowany budowaniem rozwiązań analitycznych w oparciu o SQL Server i przy okazji jest studentem WWSI (Warszawska Wyższa Szkoła Informatyki), może być zainteresowany konferencją organizowaną przez tę uczelnię. Konferencja ta – odbywająca się co roku pod szyldem "Od studenta do specjalisty Business Intelligence" – jest skierowana głównie do studentów, ale gdy spojrzeć na sylwetki prelegentów – Marcin Szeliga (SQL Server MVP), Grzegorz Stolecki (SQL Server MVP) czy wspomniany Włodek Bielski, wydaje mi się, że każdy entuzjasta hurtowni, BI i data miningu może znaleźć tam coś dla siebie. Ja również będę miał przyjemność wystąpienia na tej konferencji. Zaprezentuję temat "Władcy Danych – wykorzystanie Master Data Services do zapanowania nad wszechobecnym chaosem". Prezentacja będzie poświęcona nowemu narzędziu do zarządzania różnymi reprezentacjami danych w rozproszonych środowiskach – Master Data Services. Konferencja odbędzie się 8 grudnia w budynku uczelni. Więcej informacji na stronie pod linkiem powyżej. Niestety, z tego, co wiem, konferencja jest przeznaczona wyłącznie dla studentów WWSI. Spróbuję się zorientować, czy będą jakieś nagrania z prezentacji i ew. materiały udostępnione publicznie.

I wreszcie wisienka na torcie. SQLDay 2012 czyli doroczna konferencja organizowana przez PLSSUG we Wrocławiu. Znamy już daty – 25 i 26 maja przyszłego roku – a więc warto zarezerwować sobie te dwa dni (a najlepiej także 24 maja). Dwa dni, a więc coś nowego (do tej pory wszystkie edycje były jednodniowe). Co więcej, od obecnego prezesa PLSSUG, Tobiasza "Anoraka" Koprowskiego, wiem, że swój udział zapowiedziało kilku zagranicznych prelegentów, wybitnych specjalistów w zakresie systemu SQL Server (naprawdę głośne nazwiska, sądzę, że niebawem pojawią się na witrynie konferencji). Zapowiada się znakomity zlot pasjonatów, geeków i innych SQL-owych zboczeńców :-)

To tyle informacji, a zarazem mojego blogowania na dzisiaj. A teraz czas zaprzyjaźnić się z SQL Server 2012 RC0, którego wczoraj udało mi się po walce zainstalować! ;-)

[PL] Najlepsze praktyki dla programisty T-SQL – collation i "obce znaczki"

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Na tegorocznej konferencji Microsoft Technology Summit (MTS) przedstawiłem wraz z Markiem Adamczukiem prezentację pt. "Najlepsze praktyki dla programisty Transact-SQL". Po tej sesji sporo osób prosiło mnie o materiały, a głównie demonstracje. Dobra informacja jest taka, że materiały te można już pobrać ze strony konferencji. Najwięcej dyskusji po prezentacji dotyczyło fragmentu poświęconego collation i pracy z danymi tekstowymi pochodzącymi z różnych języków. Dlatego, po rozmowie z Markiem, postanowiłem napisać niniejszy artykuł, w którym omówię wybrane najlepsze praktyki posługując się kodem zaprezentowanym na MTS.

Nvarchar – N ma znaczenie

Typy danych nchar i nvarchar umożliwiają przechowywanie w bazie danych tekstów zawierających znaki charakterystyczne dla różnych języków. Przykładowo, mamy bazę w collation "rosyjskim", a w jednej z kolumn w tabeli w tej bazie chcemy przechować tekst w języku polskim. Wówczas typ danych nvarchar doskonale nadaje się do przechowywania danych (co ciekawe, kolumna tego typu ma nadal przypisane collation "rosyjskie"). Co jest jednak istotne w takim przypadku? Ważne jest, by przy używaniu literałów tekstowych dawać systemowi SQL Server znać, że podany tekst ma być traktowany jako Unicode. Do tego służy prefiks N umieszczany bezpośrednio przed literałem (wielkość litery ma znaczenie). Poniższy przykład dobrze obrazuje tę zasadę. Bez prefiksu N polskie znaki w napisie, który otrzymuje collation bazy danych, po prostu znikają (w niektórych przypadkach zamiast znaków charakterystycznych dla różnych alfabetów pojawiają się znaki zapytania lub inne "krzaczki"). Po dodaniu prefiksu N polskie znaki są wstawiane w kolumnę typu nvarchar bez problemu, mimo że collation bazy i kolumny jest "rosyjskie".

--Tworzymy "rosyjską" bazę
USE master;
GO
IF DB_ID('RussianDB') IS NOT NULL BEGIN
  ALTER DATABASE RussianDB SET SINGLE_USER
  WITH ROLLBACK IMMEDIATE;
  DROP DATABASE RussianDB;
END;
GO
CREATE DATABASE RussianDB COLLATE Cyrillic_General_CI_AS;
GO
 
USE RussianDB;
GO
 
--Tabela z kolumną nvarchar
CREATE TABLE dbo.Tab (c nvarchar(20) NULL);
GO
 
--Wstawiamy dane
INSERT INTO dbo.Tab (c) SELECT 'ąęśćłóżźń';
GO
 
--Test
SELECT * FROM dbo.Tab;
GO
 
--A teraz zróbmy to, jak trzeba
INSERT INTO dbo.Tab (c) SELECT N'ąęśćłóżźń';
GO
 
--Test
SELECT * FROM dbo.Tab;
GO

Długa czy krótka kolacja?

W SQL Server mamy bogactwo możliwych do wyboru collation. Zawsze, gdy tworzymy nową bazę danych, stajemy przed wyborem, jakie collation nadać tworzonej bazie? Pierwsza myśl – niech baza ma takie collation, jak bazy systemowe (czyli takie collation, jakie wybraliśmy przy instalacji SQL Servera). A jeśli ma mieć inne collation? Co wybierać – collation SQL-owe (prefiks SQL_ – zwane dalej "długim collation") czy raczej collation rodem z systemu Windows (np. Polish_CI_AS – zwane dalej "krótkim collation")? Istnieje kilka przesłanek przemawiających na korzyść collation "Windowsowych". Pierwsza przesłanka – niejawne rzutowania w przypadku, gdy do kolumny o "długim collation" spróbujemy wstawić dane typu nvarchar. Wówczas niejawna konwersja kolumny na nvarchar spowoduje niemożliwość wykorzystania ewentualnego indeksu (i odbędzie się skanowanie tabeli). W przypadku kolumny z "krótkim collation" problem znika – dane Unicode są rzutowane do typu varchar i indeks może zostać wykorzystany.

--Tabela z "długim" collation
CREATE TABLE #t1 (
  c1 varchar(128)
    COLLATE SQL_Polish_CP1250_CS_AS NOT NULL
  );
CREATE CLUSTERED INDEX IX_1 ON #t1 (c1);
GO
 
--Tabela z "krótkim" collation
CREATE TABLE #t2 (
   c2 varchar(128) COLLATE Polish_CI_AS NOT NULL
   );
CREATE CLUSTERED INDEX IX_2 ON #t2 (c2);
GO
 
--Dane
INSERT INTO #t1 (c1)
SELECT name FROM sys.all_objects;
GO
INSERT INTO #t2 (c2)
SELECT name FROM sys.all_objects;
GO
 
--Test
SELECT * FROM #t1 WHERE c1 = N'objects';
SELECT * FROM #t2 WHERE c2 = N'objects';
GO

image

Innym zachowaniem "długich collation", które może być powodem do zaniechania ich wykorzystywania, jest sortowanie tekstów, w których pojawiają się myślniki. W zasadzie komentarz jest zbędny – wystarczy rzut oka na wyniki zapytania z sortowaniem, by stwierdzić, że wynik dla "długiego collation" jest dość nieoczekiwany.

--Zmieńmy zawartość
TRUNCATE TABLE #t1;
TRUNCATE TABLE #t2;
INSERT INTO #t1 (c1)
VALUES ('a'), ('a-'), ('a-a');
INSERT INTO #t2 (c2)
VALUES ('a'), ('a-'), ('a-a');
GO
 
--Problem sortowania i myślników
SELECT * FROM #t1 ORDER BY c1;
SELECT * FROM #t2 ORDER BY c2;
GO

image

Collation a tabele tymczasowe

Jeśli już zdecydujemy się na wybór dla bazy danych collation innego niż collation serwera, musimy liczyć się z tym, że nasza nowo utworzona baza będzie miała inne collation niż baza tempdb. Co za tym idzie? Gdy będziemy używali tabel tymczasowych w kodzie proceduralnym w naszej bazie, możemy napotkać na konflikty collation w sytuacjach, gdy będą wykonywane operacje porównywania czy sortowania tekstu.

USE RussianDB;
GO
 
IF OBJECT_ID('dbo.T11', 'U') IS NOT NULL
  DROP TABLE dbo.T11;
GO
CREATE TABLE dbo.T11 (
  c11 varchar(128) NOT NULL
);
GO
INSERT INTO dbo.T11 (c11)
VALUES ('MTS');
GO
 
IF OBJECT_ID('tempdb.dbo.#T11', 'U') IS NOT NULL
  DROP TABLE #T11;
GO
CREATE TABLE #T11 (
  c11 varchar(128) NOT NULL
);
GO
 
-- Test - konflikt collation
SELECT * FROM dbo.T11
UNION
SELECT * FROM #T11;
GO
Msg 468, Level 16, State 9, Line 3
Cannot resolve the collation conflict between "Polish_CI_AS" and "Cyrillic_General_CI_AS" in the UNION operation.

Rozwiązanie połowiczne – użyć składni SELECT INTO do stworzenia tabeli tymczasowej jako kopii istniejącej tabeli. Wówczas collation kolumn tekstowych są identyczne z tymi z tabeli źródłowej.

IF OBJECT_ID('tempdb.dbo.#T11', 'U') IS NOT NULL
  DROP TABLE #T11;
GO
SELECT TOP 0 * INTO #T11 FROM dbo.T11;
GO
 
-- Test: ciut lepiej, bo działa
SELECT * FROM dbo.T11
UNION
SELECT * FROM #T11;
GO

Nie zawsze jednak mamy tabelę wzorcową, na której możemy oprzeć tabelę tymczasową. Dlatego najlepszym rozwiązaniem wydaje się być użycie klauzuli COLLATE DATABASE_DEFAULT. Wówczas kolumna tekstowa otrzymuje collation identyczne z tym, jakie zostało przypisane bazie danych, w kontekście której uruchamiamy kod.

IF OBJECT_ID('tempdb.dbo.#T11', 'U') IS NOT NULL
  DROP TABLE #T11;
GO
CREATE TABLE #T11 (
  c11 varchar(128)
  COLLATE DATABASE_DEFAULT
  NOT NULL
);
GO
 
-- Test: jest dobrze :)
SELECT * FROM dbo.T11
UNION
SELECT * FROM #T11;
GO

Podsumowanie

Powyższe przykłady ilustrują pewne wybrane przeze mnie i Marka problemy dotyczące danych tekstowych w SQL Server. Oczywiście, podobnych problemów jest więcej (np. jak zmienić collation istniejącej bazy?), ale wydawało nam się, że przedstawione dema pozwolą na ominięcie najczęściej występujących pułapek. No i druga sprawa – mieliśmy tylko 60 minut na prezentację :-) W tym miejscu pragnę podziękować wszystkim, którzy byli na naszej sesji na MTS i wypełnili ankietę dotyczącą naszej prezentacji. Jest mi też niezmiernie miło, że nasz przekaz spotkał się z bardzo pozytywnym odbiorem. Gdyby była potrzeba opisania w kolejnym artykule jakiegoś fragmentu kodu z naszych demonstracji, dajcie znać, a chętnie opublikuję kolejny fragment tekstu na blogu.

[PL] SQL Server MVP Deep Dives vol. 2 już jest!

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Miło mi poinformować, że wydawnictwo Manning rozpoczęło przyjmowanie zamówień na książkę SQL Server MVP Deep Dives vo. 2, której jestem współautorem. Oficjalna premiera książki będzie miała miejsce w Redmond w czasie konferencji PASS Summit 2011. Dla osób, które nie zetknęły się z pierwszą częścią książki – SQL Server MVP Deep Dives to książka pisana przez specjalistów zajmujących się systemem SQL Server. Większość autorów to ludzie nagrodzeni przez firmę Microsoft tytułem Microsoft Most Valuable Professional. Cały dochód ze sprzedaży idzie na cel charytatywny, w przypadku drugiej odsłony książki – na organizację Operation Smile zajmującą się operowaniem rozszczepów podniebienia u dzieci. To dla mnie wielki zaszczyt być częścią tego przedsięwzięcia i szczytnej idei, jaką jest wspieranie organizacji niosących pomoc dzieciom na całym świecie. Cena książki to 47,99 dolarów US za wersję elektroniczną lub 59,99 dolarów US za wersję drukowaną. Książkę polecam każdemu, kto interesuje się zagadnieniami związanymi z SQL Serverem lub po prostu ma ochotę i środki by wesprzeć szczytny cel tego wydawnictwa.

[PL] Denali CTP3 – Nowe lepsze DBCC IND?

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Niedawno ukazała się nowa publiczna wersja Community Preview 3 (CTP3) systemu SQL Server vNext (codename Denali). Okoliczności ukazania się tej wersji były dość ciekawe, ponieważ wersja ukazała się dość niespodziewanie szybciej, niż ktokolwiek mógł podejrzewać. Jednocześnie firma Microsoft zarzuciła użytkowników bogactwem nowych wersji SQL Server 2008 R2 (Service Pack1) i 2008 (kilka Cumulative Update’ów). Jest więc co eksplorować, choć zalecam ostrożność, ponieważ z zaufanych źródeł wiem, że zwłaszcza Service Pack 1 do R2 jest źródłem licznych problemów (włącznie z tym, że dość trudno go poprawnie zainstalować).

Dopiero kilka dni temu znalazłem czas, by sprokurować sobie maszynę wirtualną do Denali CTP3. Maszyna działa pod kontrolą Windows Server 2008 SP1. Do tego trzeba było doinstalować parę rzeczy, ale na szczęście instalator wszystko dość jasno opisuje i nie ma problemów ze znalezieniem w sieci brakujących dodatków do systemu operacyjnego.

Jedną z pierwszych czynności po zainstalowaniu każdej nowej wersji SQL Servera jest w moim przypadku sprawdzenie, czy nie pojawiły się nowe widoki i funkcje dynamiczne. Uruchamiam zatem zapytanie:

SELECT 'sys.' + name
FROM sys.system_objects
WHERE [schema_id] = 4 AND name LIKE 'dm[_]%';

Przejrzenie listy w przypadku Denali CTP3 zaowocowało znalezieniem kilku ciekawych obiektów, ale najciekawszym z mojego punktu widzenia wydaje się być sys.dm_db_database_page_allocations. Jest to funkcja dynamiczna, która przyjmuje sporo parametrów: identyfikator bazy, identyfikator tabeli, identyfikator indeksu, numer partycji oraz rodzaj widoku. Lista parametrów przypomina widok sys.dm_db_index_physical_stats. Jednak nowa funkcja zwraca informacje prawie takie same, jakie dotąd można było uzyskać za pomocą polecenia DBCC IND. Możemy zatem obejrzeć, które strony wchodzą w skład konkretnego indeksu czy sprawdzić, z ilu poziomów stron dany indeks jest złożony. Przykładowe odwołanie do tej funkcji:

SELECT *
FROM sys.dm_db_database_page_allocations(
  DB_ID(),
  NULL,
  NULL,
  NULL,
  'DETAILED'
);

Przykładowy wynik (lista stron zaalokowanych dla całej bazy, widok o największej liczbie detali):

Nie muszę tłumaczyć, o ile lepiej byłoby mieć w systemie widok dynamiczny, na dodatek w pełni wspierany i udokumentowany. Do szczęścia jeszcze poproszę jakiś oficjalny zamiennik dla DBCC PAGE :-)

[PL] SQL Server – Przerwany łańcuch backupów różnicowych

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Ostatnio po raz pierwszy w życiu spotkałem się z przypadkiem przerwanego łańcucha backupów różnicowych w SQL Server. Zjawisko może i ciekawe, ale potrafi mocno zestresować DBA. Jak to wygląda i w czym problem?

Wyobraźmy sobie scenariusz. Masz hurtownię danych, VLDB o rozmiarze ponad 1TB. Baza pracuje w SIMPLE recovery model. Wykonanie jej pełnego backupu zajmuje jakieś 2-3 godziny. Backup pełen bazy został zrobiony kilka godzin wcześniej. Teraz po dokonaniu pewnych zmian w konfiguracji bazy decydujesz się na wykonanie backupu różnicowego (differential backup). Ale przy próbie wykonania takiego backupu pojawia się komunikat:

Msg 3035, Level 16, State 1, Line 1
Cannot perform a differential backup for database "DataWarehouse", because a current database backup does not exist.
Perform a full database backup by reissuing BACKUP DATABASE, omitting the WITH DIFFERENTIAL option.
Msg 3013, Level 16, State 1, Line 1
BACKUP DATABASE is terminating abnormally.

Ale jak to? Przecież Ty wiesz, że pełen backup bazy został wykonany i leży sobie na dysku! Co się wydarzyło przez te parę godzin, że SQL Server nie pozwala Ci wykonać kopii różnicowej? Pierwszą podpowiedź znajdziesz w errorlogu SQL Servera. W czasie, gdy wykonywał się pełen backup zapewne pojawiły się w errorlogu komunikaty w stylu:

I/O is frozen on database DataWarehouse. No user action is required. However, if I/O is not resumed promptly, you could cancel the backup.

Powyżej pewnie zobaczysz (pewnie nawet zalogowane w tej samej sekundzie):

I/O was resumed on database DataWarehouse. No user action is required.

Hmmm… Pierwsza myśl – coś z dyskiem :-) Ale to nie to.

Sprawdźmy historię backupów naszej bazy danych (nie pamiętam, skąd wziąłem skrypt, ale w razie czego można posłużyć się fajnym kawałkiem kodu z bloga Roberta Kubalskiego):

SELECT
  bs.backup_finish_date,
  DATEDIFF(second, bs.backup_start_date, bs.backup_finish_date) AS time_taken_sec,
  CASE bs.type
    WHEN 'D' THEN 'Full'
    WHEN 'L' THEN 'Log'
    WHEN 'I' THEN 'Differential'
    ELSE ''
  END AS backup_type,
  CONVERT(decimal(15, 2), bs.backup_size / (1024. * 1024)) AS backup_size_mb,
  bmf.physical_device_name
FROM   msdb.dbo.backupmediafamily  as bmf
   INNER JOIN msdb.dbo.backupset as bs ON bmf.media_set_id = bs.media_set_id
WHERE (CONVERT(datetime, bs.backup_start_date, 102) >= GETDATE() - 7)
AND bs.database_name = N'DataWarehouse'
ORDER BY bs.backup_finish_date DESC;

Przykładowy wynik:

Co widzimy? Ano, zapewne wśród wyświetlonych informacji pojawią się backupy, które w kolumnie physical_device_name będą miały dziwaczne “szlaczki” w stylu {CBE47A8D-BF0C-4C9E-B3D4-841E16793FA8}10. Ponadto, owe podejrzane backupy będą miały równie podejrzany maleńki rozmiar (w prezentowanym powyżej przykładowym wyniku pełen backup bazy o rozmiarze 1GB zajął ponoć 0.01MB). O czym świadczą te objawy (komunikaty w errorlogu, dziwne wpisy w historii backupów oraz problem z wykonaniem backupu differential)?

Problem okazał się powszechnie (?) znany i dość wiekowy, bo nawet doczekał się swojego KB: http://support.microsoft.com/kb/903643 (a jak poszukać, to jest pewnie sporo pokrewnych KB, np. http://support.microsoft.com/kb/937683). A więc wszystkiemu winien jest działający spod systemu operacyjnego program do robienia kopii zapasowych plików, który potrafi używać Volume Shadow Copy do backupowania plików baz danych nawet, gdy są one używane przez SQL Server. Niestety, robi to kosztem backupów natywnych SQL Servera. Jeśli zdarzy się, że oba backupy – natywny backup w SQL Serverze i backup z poziomu systemu operacyjnego (niekoniecznie ntbackup, bo okazuje się, że narzędzia firm trzecich też używają tego samego mechanizmu) – wykonują się w tym samym czasie, może zostać przerwany łańcuch backupów różnicowych i nie będziesz w stanie zrobić backupu differential. A to może być czasem fatalne w skutkach. Rozwiązaniem oczywistym jest – bazy danych SQL Servera backupować wyłącznie natywnym mechanizmem (z kodu T-SQL) lub narzędziami dedykowanymi do backupowania baz SQL Servera. Jednak czasem nie da się wytłumaczyć administratorowi sieci korporacyjnej, że nie powinien używać innych narzędzi do backupowania plików baz danych. Wówczas pomocne może okazać się wyłączenie usługi SQL Server VSS Writer, dzięki której możliwe jest właśnie backupowanie plików działających baz przez “windowsowe” narzędzia.

Na koniec wypadałoby napisać, jak wykrywać takie anomalie. Próbowałem przeglądać strony DIFF bazy potraktowanej narzędziem NTBackup, ale nie znalazłem żadnej (nie-)prawidłowości, która sugerowałaby, że łańcuch backupów differential jest przerwany. Jedyne, co przychodzi mi więc do głowy, to sprawdzać w historii backupów danej bazy, czy physical_device_name jednego z ostatnich backupów zawiera coś innego niż ścieżkę do pliku. Jeśli zamiast ścieżki widzisz wspomniane wyżej “krzaki”, to może się okazać, że właśnie dotknął Cię opisany problem. Jeśli ktoś ma lepszy pomysł na detektor zerwanego łańcucha backupów differential, niech się podzieli :-)

[PL] SQL Server – Jak optymalizator robi ze mnie głupca

VN:F [1.7.9_1023]
Rating: 5.0/5 (1 vote cast)

Dawno, dawno temu dowiedziałem się z bloga Tibora Karasziego (SQL Server MVP), że optymalizator może wykorzystać obiekty constraint, takie jak CHECK czy FOREIGN KEY (klucz obcy) do optymalizacji określonych klas zapytań.

Jakiś czas temu próbowałem pokazać koledze z firmy, jak to działa i przy okazji dowiedziałem się ciekawej rzeczy, na którą dotąd nie natrafiłem. A w zasadzie, można powiedzieć, normalnie aż zgłupiałem :-)

Na początek weźmy tabelę:

USE tempdb;
GO
IF OBJECT_ID('dbo.Employee') IS NOT NULL
  DROP TABLE dbo.Employee;
CREATE TABLE dbo.Employee (
  EmployeeId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  FirstName varchar(50) NOT NULL,
  LastName varchar(50) NOT NULL,
  Income money NOT NULL DEFAULT (0)
);
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT CK_Employee_Income CHECK (Income >= 0);
GO
INSERT INTO dbo.Employee (FirstName, LastName, Income)
SELECT NEWID(), NEWID(), RAND(CHECKSUM(NEWID())) * v1.number + v2.number
FROM master.dbo.spt_values AS v1, master.dbo.spt_values AS v2
WHERE v1.type = 'P' AND v2.type = 'P'
AND v1.number BETWEEN 1 AND 1000
AND v2.number BETWEEN 1 AND 1000;
GO

Tabela dość typowa. I zawiera milion rekordów. To, co ważne, to fakt, że założyłem w niej warunek ograniczający możliwe wartości kolumny Income (muszą być nieujemne). Świeżo założony w powyższy sposób warunek CHECK jest “trusted” (patrz wpis na blogu Tibora). Weźmy teraz zapytanie:

SELECT *
FROM dbo.Employee
WHERE Income < 0;
GO

Plany wykonania na mojej maszynie i przy konfiguracji serwera z MAXDOP = 0 wygląda u mnie tak:

image

Hę? Spodziewałem się, że zobaczę operator Constant Scan i… tyle! A tymczasem jakiś skan, z jakimś parallelismem… Horror!

Pobawiłem się trochę tym zapytaniem. Pierwsza myśl – wyeliminować parallelism:

SELECT *
FROM dbo.Employee
WHERE Income < 0
OPTION (MAXDOP 1);
GO

Plan wykonania:

image

Noooo, to lubimy :-) Żadnego zbędnego zaglądania do tabeli, po prostu od razu na podstawie zaufanego warunku CHECK generowana jest odpowiedź, że nie ma rekordów spełniających warunek z zapytania.

A teraz deser – przyznaję, że sam tego nie wymyśliłem (zbyt fikuśne :-)), choć testowałem różne śmieszne warianty zapytań (m.in. dodawałem grupowania po wszystkich kolumnach tabeli – pomagało i wymuszało Constant Scan). Maciek Pilecki, z którym ten problem przedyskutowałem i który, podobnie jak ja, ma wrażenie, że coś tu nie gra, wypróbował taki kwiatek:

SELECT *
FROM dbo.Employee
WHERE Income < 0
OPTION (MAXDOP 0);
GO

Efekt? Sami sprawdźcie, ale gwarantuję pełne zaskoczenie :-) Oczywiście, Constant Scan! I o so chosi?

Wygląda na to, że optymalizator pozostawiony samemu sobie i stojący przed “trudnym” wyborem (nie wpisując hinta powodujemy, że optymalizator ma do dyspozycji wszystkie możliwe ścieżki optymalizacji zapytania) robi głupotę. A może to nowy bug? Ale plan dla zapytania z MAXDOP = 0 powoduje już moją konsternację. Trzeba będzie z kimś z grupy produktowej o tym porozmawiać, bo bardzo nie lubię tłumaczyć się przed kolegami, którym demonstruję “niby dobrze znane” triki optymalizacyjne, a tymczasem optymalizator krzyżuje moje plany i wychodzę na głupca :-)

Wszelkie przemyślenia własne na temat powyższego mile widziane. Moje przemyślenie – nigdy nie bądź niczego pewnym na 100% bez sprawdzenia organoleptycznie :-)

Dodam, że przełączenie MADXOP = 1 na poziomie serwera nie zmienia sytuacji – dalej mamy skan całej tabeli, jeśli nie dodamy hinta lub nie skomplikujemy zapytania! O co tutaj chodzi??? :-)

I na sam koniec – kupa śmiechu. Jaki jest bodaj najprostszy możliwy hint wymuszający Constant Scan w omawianym przypadku? Opadają mi ręce, gdy pomyślę o mojej SQL-owej niewiedzy…

SELECT *
FROM dbo.Employee
WHERE Income < 0 AND 1=1;
GO

[EDIT] Jak słusznie zauważył Patrik Třeštik komentując ten wpis, problem jest najpewniej spowodowany przez parametryzację zapytania (i zarazem zjawisko parameter sniffing). Jakimś cudem zero w warunku WHERE przestaje być stałą i optymalizator zaczyna traktować je jak wartość nieznaną, a więc jednocześnie nie może porównać jej do wartości zaszytej w ograniczeniu CHECK. Tylko powstaje pytanie – po co ta parametryzacja? :-) [/EDIT]

[PL] SQL Server – {Workbench} Funkcje i ich “gotchas”

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Od jakiegoś czasu chodził za mną pomysł, żeby publikować na blogu obszerne fragmenty kodu, które wraz z komentarzami w nich zawartymi opisywałyby się same. Pomysł zaczerpnąłem z serii, którą dawno temu śledziłem na portalu Simple Talk (przykład). Dzisiaj pierwszy workbench na moim blogu – poświęcony pułapkom w systemowych funkcjach skalarnych (kod trzymam od dawna, więc pomyślałem, że czas go opublikować). Prawie na pewno nie będzie to ostatni workbench, jaki opublikuję. A gdyby komuś przyszło do głowy, co by można było dopisać do listy poniższych “gotchas”, śmiało dodawajcie w komentarzach albo ślijcie na maila (najlepiej od razu w takiej postaci, jak poniżej). Creditsy gwarantowane :-)

/*
 
Workbench: Funkcje i ich "gotchas"
 
Cel: Pokazanie pułapek ukrytych w systemowych funkcjach
     skalarnych w SQL Server.
 
Założenie: Znajomość przedstawionych funkcji i
           umiejętność znalezienia pomocy do nich w BOL
 
Uwagi: kod zawiera tylko "gotchas", nie podaję gotowych obejść problemów
 
*/
 
------------------------------------------------------------
-- Funkcja      : DATEDIFF
-- Gotcha       : Niedziela zawsze pierwszym dniem tygodnia
-- Rozwiązanie  : Własna funkcja
------------------------------------------------------------
-- Niedziela pierwszym dniem tygodnia
SET DATEFIRST 7
-- Wynik: oczekiwane 0
SELECT DATEDIFF(week, '20110501', '20110502')
-- Poniedziałek pierwszym dniem tygodnia
SET DATEFIRST 1
-- Wynik: nieoczekiwane 0
SELECT DATEDIFF(week, '20110501', '20110502')
 
------------------------------------------------------------
-- Funkcja      : ISNULL
-- Gotcha       : Typ danych narzucany przez pierwszy parametr
-- Rozwiązanie  : Jawna konwersja lub użycie COALESCE zamiast ISNULL
------------------------------------------------------------
-- Wynik: Ala m - bo typ wynikowy to char(5)
SELECT ISNULL(CONVERT(char(5), NULL), 'Ala ma kota')
 
------------------------------------------------------------
-- Funkcja      : ISNUMERIC
-- Gotcha       : Nie zawsze mówi prawdę
-- Rozwiązanie  : Własna funkcja (CLR?)
------------------------------------------------------------
-- Wynik: 0 i 0, czyli '' nie jest liczbą,
-- ale daje się rzutować na typ liczbowy
SELECT ISNUMERIC(''), CONVERT(int, '')
 
------------------------------------------------------------
-- Funkcja      : LEN
-- Gotcha       : Przed zliczaniem znaków ucina końcowe spacje
-- Rozwiązanie  : Własna funkcja
------------------------------------------------------------
-- Wynik: 3 (zamiast 5)
SELECT LEN('abc  ')
 
------------------------------------------------------------
-- Funkcja      : QUOTENAME
-- Gotcha       : Zwraca NULL dla parametrów dłuższych niż 128 znaków
-- Rozwiązanie  : Własna funkcja
------------------------------------------------------------
-- Wynik: NULL
SELECT QUOTENAME(REPLICATE('a', 129))
 
------------------------------------------------------------
-- Funkcja      : REPLICATE
-- Gotcha       : Typ danych prawie narzucany przez pierwszy parametr
-- Rozwiązanie  : Jawna konwersja pierwszego parametru
------------------------------------------------------------
-- Wynik: 7998, bo kolejna trójka nie mieści się w 8000,
-- a typ varchar(max)/nvarchar(max) musi być wskazany jawnie
SELECT LEN(REPLICATE(CONVERT(char(3), 'abc'), 3000))
 
------------------------------------------------------------
-- Funkcja      : SERVERPROPERTY
-- Gotcha1      : Dla "nieznanej" wartości parametru zwraca NULL
-- Gotcha2      : Zwraca wartość typu sql_variant (jak inne funkcje *PROPERTY)
-- Rozwiązania  : Uważać na parametr + jawna konwersja wyniku
------------------------------------------------------------
-- Wynik: NULL i nazwa_maszyny
SELECT SERVERPROPERTY('MachinName'), SERVERPROPERTY('MachineName')
-- Wynik: Błąd
-- Msg 402, Level 16, State 1, Line 1
-- The data types varchar and sql_variant are incompatible in the add operator.
SELECT 'Nazwa maszyny: ' + SERVERPROPERTY('MachineName')
 
------------------------------------------------------------
-- Funkcja      : STR
-- Gotcha       : Czasem zwraca "gwiazdki" :-)
-- Rozwiązania  : Podawać dwa parametry lub nie używać STR
------------------------------------------------------------
-- Wynik: ********** i 12345678901
-- Pierwsze wyrażenie zwraca wartość typu char(10),
-- a gwiazdki to wynik zwracany przez STR przy przekroczeniu
-- długości określonej przez drugi opcjonalny parametr (domyślnie 10)
SELECT STR(12345678901), STR(12345678901, 11)