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.
USE [master];
GO
IF DATABASEPROPERTY('TestDb', 'Version') > 0
BEGIN
ALTER DATABASE [TestDb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [TestDb];
END
GO
CREATE DATABASE [TestDb];
GO
USE [TestDb];
GO
CREATE TABLE [dbo].[Table1]
(
[col1] int identity(1,1),
[col2] char(1) DEFAULT 'a'
);
GO
INSERT INTO [dbo].[Table1] DEFAULT VALUES;
GO 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.
SET STATISTICS IO ON;
ALTER TABLE [dbo].[Table1]
ADD [col3] datetime NOT NULL DEFAULT GETDATE();
GO
Nahát... nulla IO :). Nézzük csak meg a metaadatokat... (ezt DAC-on keresztül megy csak)
USE [TestDb]
GO
SELECT
O.[name] AS [table_name],
C.[name] AS [column_name],
DC.[name] AS [default_constraint_name],
DC.[definition] AS [current_default_constraint_definiton],
SE.[value] AS [meta_default_constraint_definition]
FROM
sys.sysseobjvalues SE
JOIN
sys.partitions P ON SE.[id] = P.[partition_id]
JOIN
sys.objects O ON P.[object_id] = O.[object_id]
JOIN
sys.columns C ON O.[object_id] = C.[object_id] AND SE.[subid] = C.[column_id]
JOIN
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.
SET STATISTICS IO ON;
ALTER TABLE [dbo].[Table1]
ADD [col4] uniqueidentifier NOT NULL DEFAULT NEWID();
GO
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!