Tohle prostě není možné. Viz Uvnitř Storage Engine:Anatomie záznamu
Za předpokladu, že váš stůl je něco takového.
CREATE TABLE T1(
col_1 varchar(8000) NULL,
col_2 varchar(8000) NULL,
/*....*/
col_999 varchar(8000) NULL,
col_1000 varchar(8000) NULL
)
Pak dokonce řádek se všemi NULL
hodnoty budou používat následující úložiště.
- 1 bajtové stavové bity A
- 1 bajt stavových bitů B
- Posun počtu sloupců o 2 bajty
- 125 bajtů
NULL_BITMAP
(1bit
na sloupec pro 1 000 sloupců)
To je tedy garantovaných 129 již spotřebovaných bajtů (zbývá 7 931).
Pokud má některý ze sloupců hodnotu, která není ani NULL
nebo prázdný řetězec, pak také potřebujete místo pro
- Počet sloupců s proměnnou délkou 2 bajty (zbývá 7 929).
- Kdekoli mezi 2–2000 bajty pro pole posunu sloupců.
- Samotná data.
Pole offsetu sloupců spotřebuje 2 bajty na sloupec s proměnnou délkou s výjimkou pokud tento sloupec a všechny následující sloupce mají také nulovou délku. Aktualizace col_1000
by vynutilo použití celých 2000 bajtů při aktualizaci col_1
by použil pouze 2 bajty.
Takže byste mohli naplnit každý sloupec 5 bajty dat a při zohlednění 2 bajtů každého v poli posunu sloupců by to dalo až 7 000 bajtů, což je v rámci zbývajících 7 929.
Data, která ukládáte, jsou však 102 bajtů (51 nvarchar
znaků), takže to lze uložit mimo řádek s 24bajtovým ukazatelem na aktuální data zbývající v řádku.
FLOOR(7929/(24 + 2)) = 304
Nejlepším případem by tedy bylo, že byste mohli uložit 304 sloupců této délky dat, a to v případě, že aktualizujete z col_1
, col_2
, ...
. Pokud col_1000
obsahuje data, pak je výpočet
FLOOR(5929/24) = 247
Pro NTEXT
výpočet je podobný kromě může použít 16bajtový ukazatel
což by vám umožnilo vtěsnat data do několika dalších sloupců
FLOOR(7929/(16 + 2)) = 440
Potřeba dodržovat všechny tyto ukazatele mimo řádek pro jakýkoli SELECT
v porovnání s tabulkou by to pravděpodobně velmi poškodilo výkon.
Skript pro testování
DROP TABLE T1
/* Create table with 1000 columns*/
DECLARE @CreateTableScript nvarchar(max) = 'CREATE TABLE T1('
SELECT @CreateTableScript += 'col_' + LTRIM(number) + ' VARCHAR(8000),'
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 1000
ORDER BY number
SELECT @CreateTableScript += ')'
EXEC(@CreateTableScript)
/* Insert single row with all NULL*/
INSERT INTO T1 DEFAULT VALUES
/*Updating first 304 cols succeed. Change to 305 and it fails*/
DECLARE @UpdateTableScript nvarchar(max) = 'UPDATE T1 SET '
SELECT @UpdateTableScript += 'col_' + LTRIM(number) + ' = REPLICATE(1,1000),'
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 304
ORDER BY number
SET @UpdateTableScript = LEFT(@UpdateTableScript,LEN(@UpdateTableScript)-1)
EXEC(@UpdateTableScript)