Új oszlop hozzáadása egy táblához - harmadik rész
Hol is kezdjem... pár éve írtam egy bejegyzést erről, majd mégegyet, mert felmerült pár kérdés még ezzel kapcsolatban. Az elmúlt héten ismét egy érdekes dolog jött szembe. Alapvetően SQL Server 2012-es verziótól az új oszlop hozzáadása egy táblához "csak" metaaadat változás. A részletek a két hivatkozott cikkben vannak. Igen ám, de mi van akkor ha nem egy statikus értéket vagy egy determinisztikus függvényt akarok megadni a DEFAULT értéknek??? :) Még továbbmegyek: mi van akkor ha a GETDATE vagy a CURRENT_TIMESTAMP függvényeket akarom hozzáadni? Ugye ezek nem determinisztikus függvények :) Szóval, ismételjük meg az előző kísérletet és lássuk mi lesz belőle.
1USE [master];
2GO
3
4IF DATABASEPROPERTY('TestDb', 'Version') > 0
5 BEGIN
6 ALTER DATABASE [TestDb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
7 DROP DATABASE [TestDb];
8 END
9GO
10
11CREATE DATABASE [TestDb];
12GO
13
14USE [TestDb];
15GO
16
17CREATE TABLE [dbo].[Table1]
18(
19 [col1] int identity(1,1),
20 [col2] char(1) DEFAULT 'a'
21);
22GO
23
24INSERT INTO [dbo].[Table1] DEFAULT VALUES;
25GO 2000
A fenti kód létrehozza a teszt adatbázisomat és egy táblát 2000 sorral. Na akkor adjunk hozzá egy új oszlopot, most a GETDATE legyen az alap érték. Az egyszerűség kedvéért, azt akarom megnézni, hogy van e IO művelet az ALTER TABLE során. Ehhez a STATISTICS IO-t bekapcsolom.
1SET STATISTICS IO ON;
2ALTER TABLE [dbo].[Table1]
3ADD [col3] datetime NOT NULL DEFAULT GETDATE();
4GO
Nahát... nulla IO :). Nézzük csak meg a metaadatokat... (ezt DAC-on keresztül megy csak)
1USE [TestDb]
2GO
3
4SELECT
5 O.[name] AS [table_name],
6 C.[name] AS [column_name],
7 DC.[name] AS [default_constraint_name],
8 DC.[definition] AS [current_default_constraint_definiton],
9 SE.[value] AS [meta_default_constraint_definition]
10FROM
11 sys.sysseobjvalues SE
12JOIN
13 sys.partitions P ON SE.[id] = P.[partition_id]
14JOIN
15 sys.objects O ON P.[object_id] = O.[object_id]
16JOIN
17 sys.columns C ON O.[object_id] = C.[object_id] AND SE.[subid] = C.[column_id]
18JOIN
19 sys.default_constraints DC ON C.[default_object_id] = DC.[object_id] AND C.[column_id] = DC.[parent_column_id]
Ezek szerint a GETDATE értékét egyszer letárolta és az ALTER TABLE idejét veszi majd. Érdekes :) Na most próbáljunk egy másik függvényt, pl. NEWID(). Ez már érdekesebb lesz.
1SET STATISTICS IO ON;
2ALTER TABLE [dbo].[Table1]
3ADD [col4] uniqueidentifier NOT NULL DEFAULT NEWID();
4GO
A kimenet:
Table 'Table1'. Scan count 1, logical reads 3460, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Itt az összes sort update-elte!!! Hajaj, így már azért érdekesebb a dolog.
A konklúzió: nem minden arany ami fénylik. Hiába metaadat változás lenne, ahogy a fentiekből is látszik ez nem mindig teljesül. Érdmes tesztelni, mielőtt egy új oszlopot adnánk egy táblához. Ezzel megelőzhető pár kellemetlen telefon is :)
Enjoy!