SQL Server 閃電般快速查詢指南 Quick Query⚡
2020-12-23
蒐羅生涯中遇見的各種 SQL Server 快捷專業的指令 ⚡
監督系統
sp_who / sp_who2
sp_who 基本查詢,主要用於判別 hostname, dbname 等資訊。
sp_who2 可以查詢到 SQL 連線 CPUTime / DIskIO / ProgramName 等資訊
令 stored procedure 可以被條件查詢的 fast script
CREATE TABLE #sp_who2 (SPID INT,Status VARCHAR(255),
Login VARCHAR(255),HostName VARCHAR(255),
BlkBy VARCHAR(255),DBName VARCHAR(255),
Command VARCHAR(255),CPUTime INT,
DiskIO INT,LastBatch VARCHAR(255),
ProgramName VARCHAR(255),SPID2 INT,
REQUESTID INT)
INSERT INTO #sp_who2 EXEC sp_who2
SELECT *
FROM #sp_who2
WHERE DBName != 'master'
ORDER BY DBName ASC
DROP TABLE #sp_who2
替代 sp_who2 的 T-sql
SELECT spid,
sp.[status],
loginame [Login],
hostname,
blocked BlkBy,
sd.name DBName,
cmd Command,
cpu CPUTime,
physical_io DiskIO,
last_batch LastBatch,
[program_name] ProgramName
FROM master.dbo.sysprocesses sp
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
ORDER BY spid
取得資料庫伺服器硬體資訊
搭配本機資料庫伺服器群組查詢更為方便 😁
SELECT
cpu_count,
hyperthread_ratio,
socket_count,
physical_memory_kb / 1024 / 1024 as 'RAM (GB)'
FROM sys.dm_os_sys_info
SQL Server 2008 (含) 以前的版本不支援 socket_count
以及 physical_memory_kb
,必須使用替代方式:
SELECT
cpu_count,
hyperthread_ratio,
0 'socket_count',
physical_memory_in_bytes / 1024 / 1024 / 1024 as 'RAM (GB)'
FROM sys.dm_os_sys_info
確認所有的 SQLServerAgent Service 有正常服務
EXEC xp_servicecontrol 'querystate', 'SQLServerAgent'
其他確認方式,使用 sys.dm_server_services
SELECT servicename, startup_type_desc, status_desc, service_account FROM sys.dm_server_services
Login 系列
列出所有資料庫的 db_owner
DECLARE @Table TABLE
(
ServerName SYSNAME,
DbName SYSNAME,
UserName SYSNAME,
TypeOfLogIn VARCHAR(100),
PermissionLevel VARCHAR(100),
TypeOfRole VARCHAR(100)
)
INSERT @Table
EXEC sp_MSforeachdb '
use [?]
BEGIN
SELECT
ServerName=@@servername,
dbname=db_name(db_id()),
p.name AS UserName,
p.type_desc AS TypeOfLogin,
pp.name AS PermissionLevel,
pp.type_desc AS TypeOfRole
FROM sys.database_role_members roles
JOIN sys.database_principals p ON roles.member_principal_id = p.principal_id
JOIN sys.database_principals pp ON roles.role_principal_id = pp.principal_id
WHERE pp.name = ''db_owner'' and p.name != ''dbo''
END '
SELECT * FROM @Table
Create Login / Drop Login
CRETAE LOGIN loginName WITH PASSWORD = 'password';
DROP LOGIN loginName;
sp_helplogins
sp_helplogins 'loginName';
sp_helpsrvrole
列出 Server Level Roles 的所有角色資訊
sp_helpsrvrole
sp_helpsrvrolemember
列出所有 Server Level 具有特定 Role 的所有 Logins
sp_helpsrvrolemember 'sysadmin'
sp_helpuser
列出 Database User 的 Role, LoginName, Default Schema
sp_helpuser
sys.syslogins
列出 Login Create Date / isEnable 等相關資訊
select *, loginname from sys.syslogins order by accdate desc
客製應用 - 尋找伺服器的 登入 以及計算權限等級
select loginname,
CASE
WHEN sysadmin = 1 then 8
WHEN securityadmin = 1 then 8
ELSE sysadmin + securityadmin + serveradmin + setupadmin + processadmin + diskadmin + dbcreator + bulkadmin
END AS SENSITIVE, /* 權限等級;越高權限越大 */
createdate,
sysadmin,
securityadmin,
serveradmin,
setupadmin,
processadmin,
diskadmin,
dbcreator,
bulkadmin
from sys.syslogins
where isntname = 0 /* 排除本機帳號*/
and (isntgroup = 1 or isntgroup = 0) /* 群組*/
order by createdate desc
/* 無法找到最近一次登入時間 */
檢視連線中的 Session 所使用的通訊協定及驗證方法
SELECT client_net_address, net_transport, auth_scheme, encrypt_option
FROM sys.dm_exec_connections
Database
sp_helpdb
查看資料庫伺服器中的所有資料庫,包含資料庫大小、擁有者、建立日期、相容性層級等資訊,無法顯示離線的資料庫。
EXEC sp_helpdb
列出資料庫伺服器中的資料庫資訊 (sys.databases)
SELECT
d.name, -- 資料庫名稱
f.physical_name, --實體檔案路徑
d.state_desc, --資料庫狀態 線上、離線、復原模式
(cast(f.size AS FLOAT)*8)/1024 AS fileSize, --實體檔案大小 MB
d.recovery_model_desc, --復原模式 完整、批次、簡單
d.compatibility_level, --相容性等級
d.create_date , f.differential_base_time --建立日期與檔案異動日期
FROM sys.master_files as f
JOIN sys.databases AS d ON f.database_id = d.database_id
簡化查詢版本,但查詢結果不容易閱讀
sp_msforeachdb 'use ?;select DB_NAME();exec sp_helpfile'
改變資料庫 Owner (sp_changedbowner)
處理錯誤訊息 「出現錯誤「無法改變使用者'dbo'」
use DatabaseName
EXEC sp_changedbowner 'sa'
取得 Exec T-SQL 中的資料 / 取用 T-SQL 的結果
取得 Table 的相關資訊 (欄位名稱)
use DatabaseName
exec sp_columns "tableName"
客製應用 - 取得資料庫所有使用的欄位型別資訊
select tb.name as TableName, t.name as ColumnType, c.* from sys.all_columns as c
join sys.types as t
on c.system_type_id = t.system_type_id
join (select name, OBJECT_ID from sys.tables) as tb
on tb.object_id = c.object_id
where t.name != 'sysname'
查詢資料庫、資料表使用的硬碟空間
方式一
EXEC sp_spaceused
一次打十個💢,缺點不容易閱讀
EXECUTE sp_MSforeachdb 'EXECUTE sp_spaceused'
⭐方式二、取得資料庫所有資料表的硬碟使用空間資訊
USE DatabaseName
Go
SELECT
t.NAME AS TableName,
--s.Name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 /1024 AS TotalSpaceMB,
SUM(a.used_pages) * 8 /1024 AS UsedSpaceMB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 /1024 AS UnusedSpaceMB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.NAME NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows
ORDER BY
t.Name
查詢資料庫中每個資料表之列數與資料表大小(容量)資訊。Get size of all tables in database
查詢 Single Database, all Tables, Rows Count
SELECT
t.NAME AS TableName,
p.rows AS RowCounts
FROM
sys.tables t
INNER JOIN
sys.partitions p ON t.object_id = p.OBJECT_ID
WHERE
t.is_ms_shipped = 0 AND p.index_id < 2
ORDER BY
TableName;
查詢資料庫實體檔案的大小與未使用大小 (SpaceUsed)
use DatabaseName
SELECT DB_NAME() AS DbName,
name AS FileName,
type_desc,
size/128.0 AS CurrentSizeMB,
size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT)/128.0 AS FreeSpaceMB
FROM sys.database_files
所有的資料庫與其所有的資料表
使用 sp_msforeachdb 顯示資料庫伺服器下所有的資料庫及其資料表,尚需要擴充下列內容:
- Database : File Size
- Table : Rows, Size
- Database Users
SET NOCOUNT ON
DECLARE @AllTables table (DbName sysname,SchemaName sysname, TableName sysname)
DECLARE
@SearchDb nvarchar(200)
,@SearchSchema nvarchar(200)
,@SearchTable nvarchar(200)
,@SQL nvarchar(4000)
SET @SearchDb='%'
SET @SearchSchema='%'
SET @SearchTable='%'
SET @SQL='SELECT ''?'' AS DbName, s.name AS SchemaName, t.name AS TableName
FROM [?].sys.tables t INNER JOIN [?].sys.schemas s ON t.schema_id=s.schema_id WHERE ''?'' LIKE '''
+ @SearchDb + ''' AND s.name LIKE ''' + @SearchSchema + ''' AND t.name LIKE ''' + @SearchTable + ''''
INSERT INTO @AllTables (DbName, SchemaName, TableName)
EXEC sp_msforeachdb @SQL
SET NOCOUNT OFF
SELECT * FROM @AllTables
WHERE DBNAME NOT IN ('tempdb')
ORDER BY DbName, SchemaName, TableName
取得所有資料庫的所有資料表的欄位與型別資訊
-- Create a temporary table to store the results
IF OBJECT_ID('tempdb..#AllDatabasesTableCounts') IS NOT NULL
DROP TABLE #AllDatabasesTableCounts;
CREATE TABLE #AllDatabasesTableCounts
(
SERVERNAME NVARCHAR(128),
DATABASE_NAME NVARCHAR(128),
TABLE_SCHEMA NVARCHAR(128),
TABLE_NAME NVARCHAR(128),
RowCounts BIGINT,
COLUMN_NAME NVARCHAR(128),
DATA_TYPE NVARCHAR(128),
CURRENT_DATETIME DATETIME
);
-- Declare variables for dynamic SQL
DECLARE @SQL AS NVARCHAR(MAX);
DECLARE @DatabaseName AS NVARCHAR(128);
-- Cursor to go through each database
DECLARE db_cursor CURSOR FOR
SELECT name
FROM sys.databases
WHERE database_id > 4 AND state = 0 -- User databases and online only
AND name not in ('DBA') -- exclude database name
-- Open cursor and fetch each database into the variable
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @DatabaseName
WHILE @@FETCH_STATUS = 0
BEGIN
-- Dynamic SQL for each database
SET @SQL = 'USE [' + @DatabaseName + '];
WITH table_count AS
(
SELECT
s.name AS SchemaName,
t.name AS TableName,
SUM(p.rows) AS RowCounts
FROM
sys.tables t
INNER JOIN
sys.partitions p ON t.object_id = p.object_id
INNER JOIN
sys.indexes i ON p.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
i.type <= 1 -- Heap or clustered index
GROUP BY
s.name, t.name
)
INSERT INTO tempdb..#AllDatabasesTableCounts
SELECT
@@SERVERNAME AS SERVERNAME,
DB_NAME() AS DATABASE_NAME,
c.TABLE_SCHEMA,
c.TABLE_NAME,
tc.RowCounts,
c.COLUMN_NAME,
c.DATA_TYPE,
GETDATE() AS CURRENT_DATETIME
FROM
INFORMATION_SCHEMA.COLUMNS c
INNER JOIN
table_count tc
ON c.TABLE_NAME = tc.TableName AND c.TABLE_SCHEMA = tc.SchemaName
ORDER BY
c.TABLE_NAME, c.ORDINAL_POSITION;';
-- Execute the dynamic SQL
EXEC sp_executesql @SQL;
-- Fetch the next database
FETCH NEXT FROM db_cursor INTO @DatabaseName
END
-- Close and deallocate the cursor
CLOSE db_cursor;
DEALLOCATE db_cursor;
-- Select results to verify
SELECT * FROM #AllDatabasesTableCounts;
Indexes
查詢資料庫中的所有索引
顯示單一資料庫的所有索引,包含名稱及碎片化程度以及分頁數量
SELECT S.name as 'Schema',
T.name as 'Table',
I.name as 'Index',
DDIPS.avg_fragmentation_in_percent,
DDIPS.page_count,
DDIPS.index_type_desc,
P.rows
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS DDIPS
INNER JOIN sys.tables T on T.object_id = DDIPS.object_id
INNER JOIN sys.schemas S on T.schema_id = S.schema_id
INNER JOIN sys.indexes I ON I.object_id = DDIPS.object_id
INNER JOIN
sys.partitions P ON I.object_id = p.OBJECT_ID
AND I.index_id = p.index_id
AND DDIPS.index_id = I.index_id
WHERE DDIPS.database_id = DB_ID()
此外也可以用於觀察建立主鍵的資料表變化 (從 Heap 變成 Clustered Index)
確認索引的使用情形
如果一片空白,可能表示資料庫從未使用!
SELECT DB_NAME(database_id) ,i.name, s.* FROM sys.dm_db_index_usage_stats s
INNER JOIN sys.indexes i
ON s.object_id = i.object_id AND s.index_id = i.index_id
WHERE database_id = db_id()
查詢推薦建立的遺失索引
SELECT * FROM sys.dm_db_missing_index_details IDS
INNER JOIN
sys.dm_db_missing_index_groups IG
ON IDS.index_handle = IG.index_handle
INNER JOIN
sys.dm_db_missing_index_group_stats IGS
ON IG.index_group_handle = IGS.group_handle
Backup Device
列出最近的備份紀錄
SELECT
CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server,
msdb.dbo.backupset.database_name,
msdb.dbo.backupset.backup_start_date,
msdb.dbo.backupset.backup_finish_date,
msdb.dbo.backupset.expiration_date,
CASE msdb..backupset.type
WHEN 'D' THEN 'Database'
WHEN 'L' THEN 'Log'
END AS backup_type,
msdb.dbo.backupset.backup_size,
msdb.dbo.backupmediafamily.logical_device_name,
msdb.dbo.backupmediafamily.physical_device_name,
msdb.dbo.backupset.name AS backupset_name,
msdb.dbo.backupset.description
FROM
msdb.dbo.backupmediafamily
INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id
WHERE
(CONVERT(datetime, msdb.dbo.backupset.backup_start_date, 102) >= GETDATE() - 7)
ORDER BY
msdb.dbo.backupset.backup_finish_date desc
RESTORE HEADERONLY
檢查備份裝置 (Backup Device) / DISK 中備份組 (Backup Set) 的詳細資訊
RESTORE HEADERONLY FROM 'DEVICENAME'
RESTORE HEADERONLY FROM DISK = N''
RESTORE FILELISTONLY
檢查備份裝置 / DISK 中還原檔的詳細資訊 (mdf, ldf, ndf)
RESTORE FILELISTONLY FROM 'DEVICENAME'
RESTORE FILELISTONLY FROM DISK = N''
Jobs
查詢 SQL Server Agent 所有的作業
SELECT
job.job_id,
notify_level_email,
name,
enabled,
description,
step_name,
command,
server,
database_name
FROM
msdb.dbo.sysjobs job
INNER JOIN
msdb.dbo.sysjobsteps steps
ON
job.job_id = steps.job_id
參考資料
Script to retrieve SQL Server database backup history and no backups