Egyéni számlálók (generátorok) szervezése a Microsoft sql szerverben

A Microsoftot rendszeresen hibáztatják az a tény, hogy az SQL Serverben még mindig nem létezik olyan példa, mint a SEQUENCE az Oracle-ben.

A felkészülés lettem érdekel, hogy ajánlatot a versenytárs, és rájött, hogy semmi, de egy régi barátja az identitás „de más-más módon” mert tudom, az üzleti igények vannak, hogy számoljanak be mindenféle azonosítók, pultok és egyéb orosz SQL Server User Group sz.

Tegyük fel, hogy van egy ciklus. Ez jó, de enyhén szólva, ha nem szükséges, először is.
Jó, hogy a SEQUENCE függvényként használható, nemcsak az asztal mezőben DEFAULT értékként, és nem kapcsolhatja össze az értéket a pillanatnyi fizikai hozzáadással.
De a legfontosabb igénnyel járó követelmények a szekvencia nevének dinamikus kialakulása (vagy bármely más megvalósítási mód, amelyet "az év / hónap elejétől kell számozni"), és legalább néhány mechanizmus hiányzik a hiányzó értékek újbóli megszerzéséről.
És ha egy üzlet nem tud legalább néhány ellenőrzési kritériumokat ilyen szekvenciák, akkor valójában nem érdekel, mi a funkciója generáló szekvencia - személyazonosító sorozatszámú vagy NEWID - nem sok a különbség, mindhárom oldatok alkalmasak egyformán rossz a számla számát és a számla.

Általában kínálnak a generációs megoldások a „business szobák” írt TSQL és táblázatok alapján a jelenlegi értékeit számlálók zhutchayshy egy hátránya - zár. Valóban, ha a „generál” új számot, abban az időben a termelés, meg kell blokkolni a pult másik kapcsolat nem kapott az azonos értékű. És mint általában, a szám kell, hogy bekerüljön egy már nyitott tranzakció, amely tele van az a tény, hogy a két eredetileg független az üzleti folyamat lesz, a legjobb, egy hosszú blokk egymást, és a legrosszabb esetben - nem annyira függetlenek, hogy elkerüljék a holtpont (holtpont).

Ezenkívül a számlálók számlálása alapján számok generálása nem "beburkolható" a függvényben, ami nagyon kívánatos lenne a forma szerkezeteinek megvalósításához:

helyezze be a MyTable-ba (DocNum.DocDate. Comment)
válassza a Generátor lehetőséget. NextValue ('SequenceFor_DocNum'), IncomeDate. megjegyzés
a #SomeBuffer-tól


mert a függvények megtiltják az adatok változását, és nem változtathatjuk meg az aktuális értéket.

De nem igazán. A funkciókban meghosszabbított tárolt eljárások és CLR eljárások és funkciók hívhatók.

De a CLR függvényben képesek vagyunk ugyanazon kiszolgálóra és adatbázisra kapcsolódni, de egy másik kapcsolaton keresztül hívjuk meg az érdeklődés számát generáló eljárást, hosszas zárolások nélkül.
Ehhez további funkciókat kell tennie a funkció írása mellett:

Most lépjünk át a "sok füzetből" egy érthetőbb T-SQL kódra.
Ami érdekes, ugyanazon a TSQL-n fogjuk magunkat csinálni - nem is kell VisualStudio, de később.

(Minden lekérdezés az adatbázisban történik, ahol számlálókra van szükségünk)

A kiszolgáló konfigurálása - CLR engedélyezése:

ha létezik (válassza ki a * -et a konfigurációból, ahol a name = 'clr enabled' és value_in_use = 0)

exec ('sp_configure' 'mutat speciális beállítások' ', 1')

exec ('sp_configure' 'clr enabled' ', 1')

Az adatbázist konfiguráljuk - lehetővé tesszük, hogy nem biztonságos összeállítások működjenek:

deklarál @ sql nvarchar (max)

set @sql = N'alter adatbázist '+ DB_NAME () + N' megbízhatóan a '

Megteremtjük a _Generator programot, amelyben a számlálókkal való manipulációhoz szükséges alapvető objektumok lesznek:
ha a SCHEMA_ID ('_Generator') null exec ('create schema _Generator')

Hozzon létre egy táblát, amelyben a számlálók paraméterei tárolásra kerülnek:

hozd létre a _Generator táblát. lista

Egyedi azonosító azonosító nem null alapértelmezett newid ().

A rendszer neve nem nulla,

StartValue int nem null korlát DF__Generator_List_StartValue alapértelmezett 0.

korlátozás PK_List_ID elsődleges kulcs fürtözött (ID),

korlátozás AK_List_Name egyedi (név)

Most hozzon létre egy triggeret, amely minden egyes számlálónak a _Generator.Listbe kerül, és létrehoz egy számláló nevét a G $ nevű programban. NextValue és CurrentValue funkciókat. Az IsWorkWithHoles paramétertől függően a NextValue függvény végrehajtása némileg eltérõ.

trigger létrehozása [_Generator]. [TR_List_UpdateGenerator] a [_Generator] -ben. [Lista]

tulajdonosként

a betét után. frissíteni. töröl

állítson be ansi_nulls-ot

@Name nvarchar (128),

Most olyan kicsit, mint a CLR-gyűlés.

Gyanítom, hogy nem minden DB-fejlesztő barátságos kapcsolatot tart fenn a C # és a VisualStudio-val, és bemutatja, hogyan kell összeállítani az összeszerelést.

Valószínűleg nagyon kevesen akarnak megbízni a gyülekezésben, dll formájában.

Ezért összeállítjuk és létrehozzuk az összeszerelést közvetlenül a T-SQL-ben. Az egyetlen követelmény az, hogy az SQL Servernek rendelkeznie kell a .NET Framework 3.5 telepítésével:

@ t táblázat (txt varchar (255))

@temp varchar (255),

@ sql varchar (8000),

@cs varchar (max)

-- Az adatbázis megbízhatóvá tétele

set @sql = 'alter database' + db_name () + 'állítsa megbízhatónak'

exec xp_cmdshell 'set'

válassza a @temp = substring (txt 6. 255)

ahol a txt, mint a "TEMP%"

set @cs = 'a Rendszer használatával;

nyilvános részosztályú PGenerator

nyilvános statikus SqlInt32 NextValue (SqlString szekvencia, SqlInt32 SPID, SqlString szervernév, SqlString adatbázisnév)

(SqlConnection IsolatedConn

= Új SqlConnection ( "Integrált Biztonsági = true; eredetileg Catalog =" + DatabaseName.ToString () + "server =" + ServerName.ToString () + "Application Name = _Generator_for_" + SPID.ToString () + „Igénybe = false "))

SqlCommand GenValue = új SqlCommand ("_ Generator.GenerateValue", IsolatedConn);

SqlParameter ret = új SqlParameter ();

SqlInt32 Val = (int) GenValue.Parameters ["ReturnValue"] Érték;

public static SqlInt32 NextValueHole (SqlString Sequence, SqlInt32 SPID, SqlString ServerName, SqlString DatabaseName)

(SqlConnection IsolatedConn

= Új SqlConnection ( "Integrált Biztonsági = true; eredetileg Catalog =" + DatabaseName.ToString () + "server =" + ServerName.ToString () + "Application Name = _Generator_for_" + SPID.ToString () + „Igénybe = false "))

SqlCommand GenValue = új SqlCommand ("_ Generator.GenerateValueHole", IsolatedConn);

SqlParameter ret = új SqlParameter ();