Това просто не е възможно. Вижте вътре в Механизъм за съхранение:Анатомия на запис
Ако приемем, че вашата маса е нещо подобно.
CREATE TABLE T1(
col_1 varchar(8000) NULL,
col_2 varchar(8000) NULL,
/*....*/
col_999 varchar(8000) NULL,
col_1000 varchar(8000) NULL
)
След това дори ред с всички NULL
стойностите ще използват следното хранилище.
- 1 байт статус битове A
- 1 байт статус битове B
- 2 байта отместване на броя на колоните
- 125 байта
NULL_BITMAP
(1bit
на колона за 1000 колони)
Така че това са гарантирани 129 байта, които вече са използвани (остават 7931).
Ако някоя от колоните има стойност, която не е NULL
или празен низ, тогава имате нужда и от място за
- 2 байта брой колони с променлива дължина (оставящи 7929).
- Някъде между 2 - 2000 байта за масива за отместване на колони.
- Самите данни.
Масивът за отместване на колони консумира 2 байта на колона с променлива дължина освен ако тази колона и всички следващи колони също са с нулева дължина. И така, актуализиране на col_1000
ще принуди да се използват целите 2000 байта, докато актуализирането на col_1
ще използва само 2 байта.
Така че бихте могли да попълните всяка колона с 5 байта данни и като вземете предвид 2 байта всеки в масива на отместването на колоната, това ще добави до 7000 байта, което е в рамките на оставащите 7929.
Въпреки това данните, които съхранявате, са 102 байта (51 nvarchar
символи), така че това може да се съхранява извън реда с 24-байтов указател към действителните данни, оставащи в реда.
FLOOR(7929/(24 + 2)) = 304
Така че най-добрият случай би бил, че можете да съхранявате 304 колони с тази дължина на данните и това е, ако актуализирате от col_1
, col_2
, ...
. Ако col_1000
съдържа данни, тогава изчислението е
FLOOR(5929/24) = 247
За NTEXT
изчислението е подобно с изключение на може да използва 16 байтов указател
което би ви позволило да свиете данни в няколко допълнителни колони
FLOOR(7929/(16 + 2)) = 440
Необходимостта да се следват всички тези указатели извън реда за всеки SELECT
срещу масата вероятно би било силно вредно за производителността.
Скрипт за тестване на това
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)