SQL SERVER 查詢語(yǔ)句備忘錄
分隔標(biāo)識(shí)符
查看指定會(huì)話 quoted_identifier 是開啟還是關(guān)閉狀態(tài):
1 select quoted_identifier 2 from sys.dm_exec_sessions 3 where session_id = @@SPID --查看當(dāng)前會(huì)話
設(shè)置當(dāng)前會(huì)話的 quoted_identifier 狀態(tài):開啟時(shí),雙引號(hào)中的內(nèi)容代表對(duì)象,如表、列等;關(guān)閉后,雙引號(hào)中的內(nèi)容代表字符串
set quoted_identifier on/off
查找一個(gè)物理頁(yè)面文件號(hào)和頁(yè)編號(hào)的三種方法:
1、使用未記錄視圖:sys.system_internals_allocation_units
select a.first_page from sys.partitions p join sys.system_internals_allocation_units a on p.partition_id = a.container_id where p.object_id = object_id('t')
以上查詢得到表 ‘t’ 的fisrt_page:0x160200000100,然后再將其轉(zhuǎn)換為文件和頁(yè)面地址。首先將其轉(zhuǎn)換(字節(jié)逆序),得到:0x 00 01 00 00 02 16 ,前兩組(字節(jié))表示文件編號(hào),后4組表示頁(yè)編號(hào)。
因此,文件編號(hào)為:0x0001(即1),頁(yè)編號(hào)為:0x00000216(即534)。
2、使用非正式文件命令:DBCC IND。如:
dbcc ind(test,t,-1)
該語(yǔ)句查詢數(shù)據(jù)庫(kù)“test”,表“t”的相關(guān)信息,其中PageType = 1(表示該頁(yè)是一個(gè)數(shù)據(jù)頁(yè))的行的前兩列即為所需的文件、頁(yè)編號(hào)。

3、使用為記錄文件函數(shù):sys.fn_PhysLocFormatter(%%physloc%%)
select sys.fn_PhysLocFormatter(%%physloc%%) as rid,* from t

查看頁(yè)面內(nèi)容:
通過上面的方法獲取到文件號(hào)(1),頁(yè)編號(hào)(534)后,通過 DBCC PAGE命令來(lái)查看該頁(yè)的具體內(nèi)容:
dbcc traceon(3604) --開啟該跟蹤標(biāo)志后,dbcc page命令才會(huì)返回結(jié)果 dbcc page(test,1,534,1) --查看數(shù)據(jù)庫(kù)test,文件號(hào)1,頁(yè)號(hào)534的頁(yè)面
DBCC PAGE 命令語(yǔ)法:DBCC PAGE ({dbid | dbname},filenum,pagenum [,printopt ])
NULL在可變長(zhǎng)度列中的存儲(chǔ)
首先創(chuàng)建測(cè)試表和數(shù)據(jù):
create table dbo.null_varchar ( id int primary key identity(1,1), c1 varchar(10) null, c2 varchar(10) null, c3 varchar(10) null, c4 varchar(10) null, c5 varchar(10) null, c6 varchar(10) null, c7 varchar(10) null, c8 varchar(10) null, c9 varchar(10) null, c10 varchar(10) null ) go set nocount on insert into null_varchar(c10) select 'a'; insert into null_varchar(c1) select 'b'; insert into null_varchar select '','','','','','','','','','c'; insert into null_varchar select 'd','','','','','','','','',''; go select * from null_varchar
查詢結(jié)果如下:

查看頁(yè)面的實(shí)際內(nèi)容:
dbcc ind(test,null_varchar,-1) --獲取文件號(hào)、頁(yè)號(hào) dbcc traceon(3604) dbcc page(test,1,544,1)
結(jié)果如下:

由第一行和第三行對(duì)比,第二行和第四行對(duì)比可以發(fā)現(xiàn):
1、NULL和空字符串的存儲(chǔ)是一樣的(除了NULL位圖不同)。
2、如果NULL或空字符串在末尾,則“可變長(zhǎng)度列的列數(shù)量”不包含這些列的數(shù)量,列偏移陣列也沒有這些列的偏移指示。
備注:對(duì)于固定長(zhǎng)度列,NULL存儲(chǔ)為0,然后由NULL位圖指示其為NULL
日期和時(shí)間
準(zhǔn)備測(cè)試語(yǔ)句:
if object_id('times','u') is not null drop table times; go create table times ( a char(1), dt1 datetime, b char(1), sd smalldatetime, c char(1), dt2 datetime2, d char(1), dt date, e char(1), dto datetimeoffset, f char(1), t time, g char(1), t0 time(0), h char(1), t1 time(1), i char(1), t2 time(2), j char(1), t3 time(3), k char(1), t4 time(4), l char(1), t5 time(5), m char(1), t6 time(6), n char(1), t7 time(7) ); go insert into times select 'a','01:02:03.123', 'b','01:02:03.123', 'c','01:02:03.123', 'd','01:02:03.123', 'e','01:02:03.123', 'f','01:02:03.123', 'g','01:02:03.123', 'h','01:02:03.123', 'i','01:02:03.123', 'j','01:02:03.123', 'k','01:02:03.123', 'l','01:02:03.123', 'm','01:02:03.123', 'n','01:02:03.123' go
結(jié)果如下:


從以上圖中可以得出以下結(jié)論:
1、對(duì)于datetime 和 smalldatetime 來(lái)說(shuō),日期部分存儲(chǔ)的是給定日期到1900-01-01的天數(shù);對(duì)于date、datetime2以及datetimeoffset來(lái)說(shuō),存儲(chǔ)的是給定日期到 0001-01-01 的天數(shù)。
對(duì)于沒有給定日期部分的日期時(shí)間數(shù)據(jù)來(lái)說(shuō),所有數(shù)據(jù)類型(datetime、smalldatetime、date、datetime2、datetimeoffset)均解釋為1900-01-01。

2、
select dt1, CAST(dt1 as varbinary(8)) as bin8, SUBSTRING(CAST(dt1 as varbinary(8)),1,4) as 日期部分, cast(SUBSTRING(CAST(dt1 as varbinary(8)),1,4) as int) as 日期部分_十進(jìn)制, SUBSTRING(CAST(dt1 as varbinary(8)),5,4) as 時(shí)間部分, cast(SUBSTRING(CAST(dt1 as varbinary(8)),5,4) as int) as 時(shí)間部分_十進(jìn)制 from times --dt1是datetime類型

select dt2,CAST(dt2 as varbinary(10)) as bin8 from times --dt2為datetime2類型
- 對(duì)于datetime來(lái)說(shuō), substring顯示的字節(jié)交換后的正常順序(日期在前,時(shí)間在后)
- 對(duì)于datetime2來(lái)說(shuō),substring顯示的是:時(shí)間精度(一個(gè)字節(jié))+ 物理存儲(chǔ)的實(shí)際二進(jìn)制串(字節(jié)交換前)
- 為啥會(huì)這樣呢?時(shí)間精度又是存儲(chǔ)在哪兒的?為啥通過dbcc page中,看不到呢?
datetime2 值強(qiáng)制轉(zhuǎn)換為 varbinary 值時(shí),會(huì)向 varbinary 值添加一個(gè)額外的字節(jié),用于存儲(chǔ)精度 。來(lái)自https://docs.microsoft.com/zh-cn/sql/t-sql/data-types/datetime2-transact-sql?view=sql-server-ver16。
添加了額外字節(jié)就不排序了?(額外字節(jié)+物理存儲(chǔ)(字節(jié)倒著放的)).
所以,上述結(jié)果0x07307C27AB085B950A:第一個(gè)字節(jié)為時(shí)間精度(07),然后再把剩下的字節(jié)逆序得到:0A 95 5B(日期部分),08 ab 27 7c 30(時(shí)間部分)
3、時(shí)間部分的轉(zhuǎn)換:
規(guī)則:對(duì)于datetime,時(shí)間部分存儲(chǔ)的是半夜之后的時(shí)鐘滴答數(shù),每滴答一次表示3.33微妙,即1/300秒。
對(duì)于datatime2,時(shí)間計(jì)算公式為(H代表銷售,M代表分鐘,S代表秒,F(xiàn)代表小數(shù)部分,D代表小數(shù)位數(shù)): ((H*60+M)*60+S) * 10^D+F
(注:01:02:03.123 的1位小數(shù)部分F表示為1 , 2位小數(shù)部分F表示為12 , 3位小數(shù)部分F表示為123,……,7位小數(shù)部分F表示為1230000)
| 數(shù)據(jù)類型 | select * from times查詢顯示 | 十進(jìn)制時(shí)間 |
| datetime | 1900-01-01 01:02:03.123 | 1116937 |
| datetime2 | 1900-01-01 01:02:03.1230000 | 37231230000 |
1):date,時(shí)間轉(zhuǎn)存儲(chǔ)
select ceiling( ((1 * 60 + 2)*60 + 3 + 0.123 )*300) -- 結(jié)果為:1116937
2):date,存儲(chǔ)轉(zhuǎn)時(shí)間
select 1116937./300 --得到3723.123333(及3723.123秒)
select 3723/60/60 --得到小時(shí):1
select (3723 % 3600) /60 --到的分鐘:2
select 3723 % 60 --得到秒:3
3):datetime2,時(shí)間轉(zhuǎn)存儲(chǔ)
select cast(((1 * 60 + 2) * 60 + 3) as bigint)*POWER(10,7) + 1230000 --結(jié)果:37231230000(datetime2默認(rèn)精度為7,所以要把小數(shù)部分補(bǔ)充到7位)
或者:select ((1 * 60 + 2) * 60 + 3 + 0.123)*POWER(10,7) --也就是把整個(gè)時(shí)間轉(zhuǎn)換成秒(3723.123秒)后,在乘以10的N次方(N為時(shí)間的精度)
4):datetime2,存儲(chǔ)轉(zhuǎn)時(shí)間
select 37231230000/POWER(10,7) --得到3723.12300000000,然后的步驟和上的第二項(xiàng)相同

浙公網(wǎng)安備 33010602011771號(hào)