Ini tidak mungkin. Lihat Di dalam Mesin Penyimpanan:Anatomi catatan
Dengan asumsi tabel Anda seperti ini.
CREATE TABLE T1(
col_1 varchar(8000) NULL,
col_2 varchar(8000) NULL,
/*....*/
col_999 varchar(8000) NULL,
col_1000 varchar(8000) NULL
)
Kemudian bahkan satu baris dengan semua NULL
nilai akan menggunakan penyimpanan berikut.
- 1 bit status bit A
- 1 bit status bit B
- Oset jumlah kolom 2 byte
- 125 byte
NULL_BITMAP
(1bit
per kolom untuk 1.000 kolom)
Jadi dijamin 129 byte sudah terpakai (meninggalkan 7.931).
Jika salah satu kolom memiliki nilai yang bukan NULL
atau string kosong maka Anda juga membutuhkan ruang untuk
- 2 byte jumlah kolom panjang variabel (meninggalkan 7.929).
- Di mana saja antara 2 - 2000 byte untuk larik offset kolom.
- Data itu sendiri.
Larik offset kolom menggunakan 2 byte per panjang variabel kolom kecuali jika kolom itu dan semua kolom berikutnya juga panjangnya nol. Jadi perbarui col_1000
akan memaksa seluruh 2000 byte untuk digunakan saat memperbarui col_1
hanya akan menggunakan 2 byte.
Jadi, Anda dapat mengisi setiap kolom dengan 5 byte data dan dengan mempertimbangkan masing-masing 2 byte dalam larik offset kolom yang akan menambahkan hingga 7.000 byte yang berada dalam sisa 7.929.
Namun data yang Anda simpan adalah 102 byte (51 nvarchar
karakter) sehingga ini dapat disimpan di luar baris dengan penunjuk 24 byte ke data aktual yang tersisa di baris.
FLOOR(7929/(24 + 2)) = 304
Jadi kasus terbaiknya adalah Anda dapat menyimpan 304 kolom dari data panjang ini dan itu jika Anda memperbarui dari col_1
, col_2
, ...
. Jika col_1000
berisi data maka perhitungannya adalah
FLOOR(5929/24) = 247
Untuk NTEXT
perhitungannya mirip kecuali dapat menggunakan pointer 16 byte
yang memungkinkan Anda memasukkan data ke dalam beberapa kolom tambahan
FLOOR(7929/(16 + 2)) = 440
Kebutuhan untuk mengikuti semua petunjuk di luar baris ini untuk setiap SELECT
bertentangan dengan meja kemungkinan akan sangat merusak kinerja.
Script untuk menguji ini
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)