Az implicit tranzakció, avagy Oracle vs MSSQL mármegint

A Millenárison tartott kiváló ITDEVCON rendezvényen részt vettem az Ask The Experts blokkban, mint SQL expert. Itt megint belefutottam a klasszikus esetbe, de árnyaltan: elmesélte egy szaktárs, hogy ő dolgozik Oracle-lel meg MSSQL-lel is, és az az ő baja a MSSQL-lel, hogy az nem tud olyat, mint az Oracle, vagyis a tranzakciókat nem lehet kényelmesen kezelni, hanem vagy az SQL Server jobban tudja, vagy pedig explicit begin tran-commit párt kell gépelni – míg az Oracle-ben nyugodtan dolgozhat, és amikor úgy gondolja, akkor commitot mond, addig meg gyűlik a redo logban a tranzakció adat. Legalábbis ő nem talált jobb megoldást. És megkérdezte, hogy vajon tudok-e én jobbat. Nos, én pedig, ki azon rugózok folyton, hogy az MSSQL enterspájz-ready, tudtam.

Az úgy van, hogy háromféle tranzakciókezelés van MSSQL-ben. Az alap az automatikus, amikor minden batchünket az SQL Server magától beteszi egy tranzakcióba, számunkra láthatatlanul és befolyásolhatatlanul. Ha azt mondjuk, hogy begin tran, akkor explicit tranzakciókezelésbe kezdünk, és tudjuk, hogy majd mondunk commit v rollback parancsot is a végén. Aki meg Oracle-n nőtt fel, az tuti hogy implicit tranzakciót fog használni. Ez attól nyílik meg, hogy kiadunk egy listázott kulcsszót (kicsit több, mint egy tucat van, a BOL-ban az igazság megint – tipikusan INSERT, UPDATE, DELETE, CREATE, DROP, stb.), és addig tart, amíg azt nem mondjuk, hogy commit. Tehát a nyitása az implicit rész. Azt kell tudni, hogy csak akkor nyílik új tranzakció, ha nincs még nyitva tranzakció. Ez a tulajdonság kapcsolatonként állítható egy SET opcióval.

Nézzünk egy egyszerű példát:

use tempdb
create table t1 (a int)
GO
-- bekapcsoljuk az implicit tranzakciókezelest
set implicit_transactions on

select @@TRANCOUNT --1, mert a SELECT kulcsszo is nyit tranzakciot!
insert into t1 values(1);

select @@TRANCOUNT -- meg mindig 1, es ugyanaz az egy
insert into t1 values(2);

select @@TRANCOUNT -- meg mindg az az 1
rollback

select @@TRANCOUNT -- 1, de ez mar egy uj
select * from t1 -- ez pedig töküres, mindkét sort kitörölte a rollback

implicit_tranJa, és ezt lehet állandóra is állítani, ha vki perverz, SSMS-ben a tools-options pont alatt a Query Editor – SQL Server – ANSI helyen, lásd mellékelt ábra. Enjoy! És ne felejtsétek el, hogy aki utoljára megy haza, kommitoljon mindenki helyett…

Keepalive

Élek, túléltem eddig mindent, és még MVP is maradtam (áprilisban van az éves megújítási köröm). És majd fogok írni is áprilisban végre.

Denali II. – CDB, avagy önjáró adatbázisok

Az egyik nagyon jópofa dolog a Denaliban a CDB, azaz (Self-)Contained Database, vagyis az öntartalmazó adatbázis. Ez a felhő meg igény szerinti dinamikus kapacitás meg egyéb buzzwordök által lesz tagelve, pedig tényleg értelmes dolog. Arról szól, hogy ha migrálni akarod az adatbázist, akkor benne van (majdnem) minden, neked nem kell loginokat, jobokat, mittoménmiket átvinned, hanem detach, attach, engedélyezet az adatbázisloginokat, jobokat az új szerveren, aztán mehet minden.

(az egyik nagyon jópofa dolog bennem meg az, hogy úgy próbáltam meg megírni ezt a postot, hogy a script hozzá a másik vinyómon maradt… :S Elnézést, mostanság kissé minimál életmódot folytatok, hála a kiváló ténynek, hogy a komplett gépparkunkat kell költöztetni, persze távolról, mert az úgy jó, ha valaki 9 órával odébb tudja csak bedugni a kábelt. most azonban rögtönzöm a scripteket a kis SQL Serveremben.)

Szóval kezdjük a loginokkal:

create database CDBTest
-- ettől lesz CDB az adatbázisunk
alter database CDBTEST SET CONTAINMENT = PARTIAL

use CDBTest
-- csinálok egy logint magamnak...
create login erik with password = 'Password1'
-- ... és csinálok egy CDB usert is. Ilyet csak CDB-ben lehet mondani!
create user erik with password = 'Password2'
-- még a szerver szintjén is be kell állítani, hogy megengedje az azonosítást CDB-ből
exec sp_configure 'contained database authentication', '1'
reconfigure
-- és most lehet tesztelni a logint

Continue reading ‘Denali II. – CDB, avagy önjáró adatbázisok’ »

SQL objektumok scriptelése Powershellben

Azt már mindenki tudja, h PS-ben lehet kiválóan scriptet generálni a SQL entitásokról a Script() metódus segítségével. Felvetődött egy kérdés vkiben, hogy hogyan lehet csak DB sémát backupolni, és felvetődött erre a Powershell, meg a get-contentitem|%{$_.Script()}, mint alapgondolat. Ja, ez ezt adja vissza egy új táblámra:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
        [day] [date] NOT NULL,
        [site] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [measurements] [smallint] NULL,
        [failures] [smallint] NULL,
        [contenterrors] [smallint] NULL,
        [availability_wc] [real] NULL,
        [availability_woc] [real] NULL,
        [errors] [varchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [loadtime] [smalldatetime] NULL,
        [comment] [varchar](2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

Szóval jól néz ki, nem? Nem. addig néz ki jól, amíg nem jut eszembe, hogy van primary key is a táblán. Meg még további indexek. Amiket persze megint ki lehet scriptelni: ˘

%{$_.Indexes}|%{$_.script()}

Meg még ki tudja, mi marad ki. Na mindegy, tuti megoldást nem tudok, de ez olyan lámának tűnt, hogy elkezdtem nézegetni a metódusokat, és találtam egy olyat, hogy EnumScript():

PS > gci |%{$_.EnumScript()}
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
        [day] [date] NOT NULL,
        [site] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [measurements] [smallint] NULL,
        [failures] [smallint] NULL,
        [contenterrors] [smallint] NULL,
        [availability_wc] [real] NULL,
        [availability_woc] [real] NULL,
        [errors] [varchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [loadtime] [smalldatetime] NULL,
        [comment] [varchar](2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_KeynoteDaily] PRIMARY KEY CLUSTERED
(
        [site] ASC,
        [day] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [ix_test] ON [dbo].[KeynoteDaily]
(
        [failures] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [ix_test2] ON [dbo].[KeynoteDaily]
(
        [measurements] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

Vagyis ő megcsinálja nekünk a rekurziót. Szerintem aranyos kényelmi szolgáltatás.
Ja, a fentiekhez a teljes path a következő volt: PS SQLSERVER:\SQL\MYCOMPUTER\DENALI\Databases\MyDatabase\Tables> . Csak a tisztánlátás kedvéért.

Denali I. – SEQUENCE vs IDENTITY

Az egyik újdonság a Denali-ban a szekvencia. Eddig ilyen volt Oracle-ben, PostgreSQL-ben, most már van MSSQL-ben is. Eddig MSSQL-ben volt IDENTITY, de az egy kicsit más. Az IDENTITY egy adott tábla sémájához kötött autoincrementes oszlop, megadott kezdőértékkel és növekedési értékkel. Értéket neki nem adunk, hanem ő magától kitölti, kivéve ha azt mondjuk, hogy SET IDENTITY_INSERT tabla ON. Az általunk utoljára felhasznált értéket a @@IDENTITY változó illetve SCOPE_IDENTITY() függvény megmondja, ha szeretnénk. Ez jó. Viszont olyan mértékben a sémához van kötve, hogy az identity tulajdonság nem változtatható. Nem lehet se rátenni egy meglévő oszlopra, se levenni róla. Ez igen fájdalmas tud lenni időnként, és én még nem tudtam feldolgozni, hogy ez miért ilyen béna.
Continue reading ‘Denali I. – SEQUENCE vs IDENTITY’ »