SQL Server自帶的系統存儲過程sp_who和sp_lock也可以用來查找阻塞和死鎖
一. 阻塞查詢 sp_lock
執行 exec sp_lock 下面列下關鍵字段
spid 是指進程ID,這個過濾掉了系統進程,只展示了用戶進程spid>50。
dbid 指當前實例下的哪個數據庫 , 使用DB_NAME() 函數來標識數據庫
type 請求鎖住的模式
mode 鎖的請求狀態
GRANT:已獲取鎖。
CNVRT:鎖正在從另一種模式進行轉換,但是轉換被另一個持有鎖(模式相沖突)的進程阻塞。
WAIT:鎖被另一個持有鎖(模式相沖突)的進程阻塞。
總結:當mode 不為GRANT狀態時, 需要了解當前鎖的模式,以及通過進程ID查找當前sql 語句
例如當前進程ID是416,且mode狀態為WAIT 時,查看方式 DBCC INPUTBUFFER(416)
用sp_lock查詢顯示的信息量很少,也很難看出誰被誰阻塞。所以當數據庫版本為2005及以上時不建議使用。
二.阻塞查詢 dm_tran_locks
SELECT t1.resource_type, t1.resource_database_id, t1.resource_associated_entity_id, t1.request_mode, t1.request_session_id, t2.blocking_session_id FROM sys.dm_tran_locks as t1 INNER JOIN sys.dm_os_waiting_tasks as t2 ON t1.lock_owner_address = t2.resource_address;
上面查詢只顯示有阻塞的會話, 關注blocking_session_id 也就是被阻塞的會話ID,同樣使用DBCC INPUTBUFFER來查詢sql語句
三.阻塞查詢 sys.sysprocesses
SELECT spid, kpid, blocked, waittime AS 'waitms', lastwaittype, DB_NAME(dbid)AS DB, waitresource, open_tran, hostname,[program_name], hostprocess,loginame, [status] FROM sys.sysprocesses WITH(NOLOCK) WHERE kpid>0 AND [status]<>'sleeping' AND spid>50
sys.sysprocesses 能顯示會話進程有多少, 等待時間, open_tran有多少事務, 阻塞會話是多少. 整體內容更為詳細。
關鍵字段說明:
spid 會話ID(進程ID),SQL內部對一個連接的編號,一般來講小於50
kipid 線程ID
blocked: 阻塞的進程ID, 值大於0表示阻塞, 值為本身進程ID表示io操作
waittime:當前等待時間(以毫秒為單位)。
open_tran: 進程的打開事務數
hostname:建立連接的客戶端工作站的名稱
program_name 應用程序的名稱。
hostprocess 工作站進程 ID 號。
loginame 登錄名。
[status]
running = 會話正在運行一個或多個批
background = 會話正在運行一個后台任務,例如死鎖檢測
rollback = 會話具有正在處理的事務回滾
pending = 會話正在等待工作線程變為可用
runnable = 會話中的任務在等待,由scheduler來運行的可執行隊列中。(重要)
spinloop = 會話中的任務正在等待調節鎖變為可用。
suspended = 會話正在等待事件(如 I/O)完成。(重要)
sleeping = 連接空閑
wait resource 格式為 fileid:pagenumber:rid 如(5:1:8235440)
kpid=0, waittime=0 空閑連接
kpid>0, waittime=0 運行狀態
kpid>0, waittime>0 需要等待某個資源,才能繼續執行,一般會是suspended(等待io)
kpid=0, waittime=0 但它還是阻塞的源頭,查看open_tran>0 事務沒有及時提交。
如果blocked>0,但waittime時間很短,說明阻塞時間不長,不嚴重
如果status 上有好幾個runnable狀態任務,需要認真對待。 cpu負荷過重沒有及時處理用戶的並發請求
--查詢所有表 SELECT NAME,* FROM SYSOBJECTS WHERE XTYPE='U' order by SYSOBJECTS.name --查詢所有存儲過程 select * from sysobjects where type='P' order by [name] --查詢表約束 exec sp_helpconstraint @objname=book_detail --@objname=prx_class go -- 查看內容(存儲過程) sp_helptext 'P_Sys_MenuList'
--查詢所有觸發器 select name from sysobjects where xtype='TR' --查詢所有視圖 select name from sysobjects where xtype='V'
--查詢觸發器與關聯表 SELECT tb2.name AS tableName,tb1.name AS triggerName FROM Sysobjects tb1 JOIN Sysobjects tb2 ON tb1.parent_obj=tb2.id WHERE tb1.type='TR' /**判斷是否存在該觸發器**/ --if exists (select * from sysobjects where id=object_id(N'Trg_IC_Log_Insert1') and type='tr') -- or if (object_id('Trg_IC_Log_Insert1','tr') is not null ) drop TRIGGER [Trg_IC_Log_Insert1] go
/*修改表命令*/
--移除主鍵 alter table tb_name drop constraint PK_name --添加多列主鍵 alter table tb_name add constraint PK_name primary key(column1,column2,column3) --修改表列名或屬性 add 增加列,drop 移除列 alter table tb_name alter column column1 varchar(10) null
--通過某個字段名稱找到數據庫中對應的表 USE Works GO select DISTINCT object_name(id) from syscolumns where name like '%the_class%' order by 1 GO ------------------------------------------ select * from sysobjects where object_name(id) in ( 'OE_ORDER_LINES_ALL', 'OE_ORDER_HEADERS_ALL', 'OE_TRANSACTION_TYPES_TL', 'FNDLOOKUPVALUES', 'HZ_CUST_SITE_USES_ALL', 'HZ_CUST_ACCT_SITES_ALL')
--sql 按默認順序排序,生成RowNum列(行號列) select identity(int,1,1) as sort,* into #temp from tb1 select * from #temp order by sort
sql 分組后根據最大值得到記錄明細
select * from 表名 as a where exists (select 1 from (select 工單編號,max(處理時間) as 處理時間 from 表名 group by 工單編號) as b where a.工單編號=b.工單編號 and a.處理時間=b.處理時間) SELECT * FROM ( select row_number() over(partition by mn order by NotesTime DESC) as number,* from T_TaskNotes ) as tb where number=1
SQLServer: 解決“錯誤15023:當前數據庫中已存在用戶或角色”
Use newzs go sp_change_users_login 'update_one', 'infos1', 'infos1' /*
其中newzs為存在孤立用戶的數據庫,update_one是存儲過程的參數,表示只處理一個用戶,前一個infos1是“用戶”,后一個infos1是“登錄”,以上這個SQL表示將服務器登錄“infos1”與 newzs數據庫用戶“infos1”重新連接起來。這樣就可以正常使用數據庫了 */
/*數據庫手動拋出錯誤異常*/ --內容 級別 RAISERROR ('678 ''數據異常'' 已經結賬' , 16, 1) WITH NOWAIT RAISERROR ('無效用戶ID。' , 16, 1)
/*分詞搜索查找*/
declare @a varchar(10) declare @s varchar(1000) declare @t table(name varchar(10)) set @a='a,b,c' set @s=right(replace(','+@a,',',''' as name union select '''),len(replace(','+@a,',',''' as name union select '''))-15)+'''' insert into @t exec(@s) select * from tb b where exists (select 1 from @t a where charindex(a.name,b.name)>0)
if object_id('[tb]') is not null drop table [tb] create table [tb] (id int,name varchar(25)) insert into [tb] select 1,'asdf富士康sfsaf' union all select 2,'富士康sdaf跳樓' union all select 3,'sdaf跳樓' union all select 4,'asdf富士康as跳樓郭台銘asf' union all select 5,'郭台銘asf' declare @name varchar(50),@sql varchar(8000) set @Name='富士康 跳樓 郭台銘' set @sql=' (case when charindex('''+replace(@name,' ',''',name)>0 then 1 else 0 end)+(case when charindex(''')+''',name)>0 then 1 else 0 end)' set @sql='select * from tb order by '+@sql+' desc'
/**全文檢索(查詢整個數據庫中某個特定值所在的表和字段的方法 )**/
一、
DECLARE @keyWord VARCHAR(200) set @keyWord='hy' -- 最大的長度. DECLARE @MaxLength INT; -- 數據庫表名稱 DECLARE @TableName VARCHAR(100); -- 數據庫表ID DECLARE @object_id INT; -- 查詢列名的SQL DECLARE @ColumnSql VARCHAR(500); -- 列名. DECLARE @clumnName VARCHAR(20); -- 查詢 數據是否存在的SQL DECLARE @Sql NVARCHAR(500); -- 查詢 數據是否存在結果 DECLARE @RowCount INT; BEGIN -- 取得 傳入的 字符串長度 -- 對於 表定義中, 字段長度小於 該長度的,將不檢索. SET @MaxLength = LEN(@keyWord); -- 定義游標. 取得所有的數據庫表名稱. DECLARE c_test_main CURSOR FAST_FORWARD FOR SELECT object_id, name FROM sys.tables -- 打開游標. OPEN c_test_main; -- 填充數據. FETCH NEXT FROM c_test_main INTO @object_id, @TableName; -- 假如檢索到了數據,才處理. WHILE @@fetch_status = 0 BEGIN -- 准備用於執行的 查詢列信息的 SQL 語句. SET @ColumnSql = 'DECLARE cur_column CURSOR for SELECT col.name ' + ' FROM sys.columns col, sys.types typ ' -- 從列視圖 與 數據類型視圖查詢 + ' WHERE ' + ' col.system_type_id = typ.system_type_id' -- 列視圖 與 數據類型視圖 關聯 + ' AND typ.name IN(''varchar'', ''nvarchar'', ''char'', ''nchar'') ' -- 只查詢指定數據類型的. + ' AND col.max_length > ' + LTRIM(STR(@MaxLength )) -- 最大長度要大於 輸入信息長度的 + ' AND col.object_id =' + LTRIM(STR(@object_id)); -- 表ID EXEC(@ColumnSql); OPEN cur_column; FETCH next FROM cur_column INTO @clumnName; WHILE @@FETCH_STATUS=0 BEGIN SET @Sql = 'SELECT @RowCount = COUNT(1) FROM ' + @TableName + ' WHERE ' + @clumnName + ' LIKE ''%' + @keyWord + '%'' '; EXEC SP_EXECUTESQL @Sql, N'@RowCount INT OUTPUT', @RowCount OUTPUT; IF @RowCount > 0 BEGIN PRINT @TableName + '.' + @clumnName; END FETCH next FROM cur_column INTO @clumnName; END CLOSE cur_column; DEALLOCATE cur_column; -- 填充下一條數據. FETCH NEXT FROM c_test_main INTO @object_id, @TableName; END; -- 關閉游標 CLOSE c_test_main; -- 釋放游標. DEALLOCATE c_test_main; END
二、
declare @sql nvarchar(max),@search nvarchar(100) set @search='hy' set @sql='' select @sql=@sql+'select top 1 '''+sysobjects.name+''' as [table],'''+syscolumns.name+''' as [columns],'+syscolumns.name+' as [value] from '+sysobjects.name+' where '+syscolumns.name+'='''+@search+''' union all ' from sysobjects inner join syscolumns on sysobjects.id=syscolumns.id where sysobjects.xtype='U' and syscolumns.xtype in (34,35,99,167,175,231,239,241,231) select @sql=@sql+'select null,null,null' exec sp_executesql @sql
三、
select convert(varchar(255),'') dsca into #y where 1=0 -- delete #y declare @s varchar(255) set @s='hy' DECLARE bbb cursor for select TABLE_NAME,column_name FROM information_schema.columns where table_name in (select table_name from information_schema.tables where TABLE_type='BASE TABLE' and table_name like '%%' ) and data_type like '%varchar%' declare @t varchar(255) declare @f varchar(255) open bbb fetch next from bbb into @t,@f while @@fetch_status=0 begin exec( ' if exists (select * from '+@t+' where '+@f+'='+''''+@s+''''+' ) insert into #y select '+''''+@t+'.'+@f+'''' ) --insert into #t select '+''''+'select * from '+@t+' WHERE '+@f+'=@F'+''' fetch next from bbb into @t,@f end close bbb deallocate bbb select * from #y drop table #y
/**全文檢索END*/
SET NOCOUNT ON;--存儲過程,當 SET NOCOUNT 為 ON 時,不返回計數(表示受 Transact-SQL 語句影響的行數)。當 SET NOCOUNT 為 OFF 時,返回計數。 declare @date datetime,@date1 datetime,@substoreid varchar(20) set @date='2014-09-22' set @date1='2014-09-30' set @substoreid='9001' --臨時表用法 select tag,code,name,num,money into #mid from ( select 1 as tag,prx_code as code,prx_name as name,sum(isnull(num,0)) as num,sum(isnull(money,0)) as money from tb1 union select 2 as tag,receive_minout.pay_class as code,name as name,0 as num,sum(isnull(money,0)) as money from tb2 ) A select * from #mid order by tag drop table #mid
--SQL每組數據只取前幾條數據的寫法 select * from (select row_number() over(partition by t.type order by date desc) rn, t.* from 表名 t) where rn <= 2; /* type要分的類 date 排序 rn 每類要顯示幾條數據 */
over partition by與group by 的區別
/*SQL執行中占CPU資源最多的前10條查詢 */ select top 20 total_worker_time/execution_count as avg_cpu_cost,plan_handle, execution_count, (select substring(text,statement_start_offset/2+1, (case when statement_end_offset=-1 then len(convert(nvarchar(max),text))*2 else statement_end_offset end - statement_start_offset)/2) from sys.dm_exec_sql_text(sql_handle)) as query_text from sys.dm_exec_query_stats order by [avg_cpu_cost] desc -- 找出工作負荷中運行最頻繁的查詢 select top 10 total_worker_time,plan_handle,execution_count, (select substring(text,statement_start_offset /2 +1, (case when statement_end_offset = -1 then len(convert(nvarchar(max),text))*2 else statement_end_offset end - statement_start_offset)/2) from sys.dm_exec_sql_text(sql_handle)) as query_text from sys.dm_exec_query_stats order by execution_count desc --找到被編譯得最多的前10位查詢計划 select top 10 plan_generation_num,execution_count, (select substring(text,statement_start_offset /2 +1, (case when statement_end_offset = -1 then len(convert(nvarchar(max),text))*2 else statement_end_offset end - statement_start_offset)/2) from sys.dm_exec_sql_text(sql_handle)) as query_text from sys.dm_exec_query_stats where plan_generation_num>1 order by plan_generation_num desc
--執行最慢的SQL語句 SELECT (total_elapsed_time / execution_count)/1000 N'平均時間ms' ,total_elapsed_time/1000 N'總花費時間ms' ,total_worker_time/1000 N'所用的CPU總時間ms' ,total_physical_reads N'物理讀取總次數' ,total_logical_reads/execution_count N'每次邏輯讀次數' ,total_logical_reads N'邏輯讀取總次數' ,total_logical_writes N'邏輯寫入總次數' ,execution_count N'執行次數' ,SUBSTRING(st.text, (qs.statement_start_offset/2) + 1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) N'執行語句' ,creation_time N'語句編譯時間' ,last_execution_time N'上次執行時間' FROM sys.dm_exec_query_stats AS qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st WHERE SUBSTRING(st.text, (qs.statement_start_offset/2) + 1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) not like '�tch%' ORDER BY total_elapsed_time / execution_count DESC; --總耗CPU最多的前個SQL: SELECT TOP 20 total_worker_time/1000 AS [總消耗CPU 時間(ms)],execution_count [運行次數], qs.total_worker_time/qs.execution_count/1000 AS [平均消耗CPU 時間(ms)], last_execution_time AS [最后一次執行時間],max_worker_time /1000 AS [最大執行時間(ms)], SUBSTRING(qt.text,qs.statement_start_offset/2+1, (CASE WHEN qs.statement_end_offset = -1 THEN DATALENGTH(qt.text) ELSE qs.statement_end_offset END -qs.statement_start_offset)/2 + 1) AS [使用CPU的語法], qt.text [完整語法], qt.dbid, dbname=db_name(qt.dbid), qt.objectid,object_name(qt.objectid,qt.dbid) ObjectName FROM sys.dm_exec_query_stats qs WITH(nolock) CROSS apply sys.dm_exec_sql_text(qs.sql_handle) AS qt WHERE execution_count>1 ORDER BY total_worker_time DESC --平均耗CPU最多的前個SQL: SELECT TOP 20 total_worker_time/1000 AS [總消耗CPU 時間(ms)],execution_count [運行次數], qs.total_worker_time/qs.execution_count/1000 AS [平均消耗CPU 時間(ms)], last_execution_time AS [最后一次執行時間],min_worker_time /1000 AS [最小執行時間(ms)], max_worker_time /1000 AS [最大執行時間(ms)], SUBSTRING(qt.text,qs.statement_start_offset/2+1, (CASE WHEN qs.statement_end_offset = -1 THEN DATALENGTH(qt.text) ELSE qs.statement_end_offset END -qs.statement_start_offset)/2 + 1) AS [使用CPU的語法], qt.text [完整語法], qt.dbid, dbname=db_name(qt.dbid), qt.objectid,object_name(qt.objectid,qt.dbid) ObjectName FROM sys.dm_exec_query_stats qs WITH(nolock) CROSS apply sys.dm_exec_sql_text(qs.sql_handle) AS qt WHERE execution_count>1 ORDER BY (qs.total_worker_time/qs.execution_count/1000) DESC
/*查詢缺失索引*/ SELECT DatabaseName = DB_NAME(database_id) ,[Number Indexes Missing] = count(*) FROM sys.dm_db_missing_index_details GROUP BY DB_NAME(database_id) ORDER BY 2 DESC; SELECT TOP 10 [Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0) , avg_user_impact , TableName = statement , [EqualityUsage] = equality_columns , [InequalityUsage] = inequality_columns , [Include Cloumns] = included_columns FROM sys.dm_db_missing_index_groups g INNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle INNER JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle ORDER BY [Total Cost] DESC;
/*將一列多行數據合並為一行*/ SELECT DISTINCT [Student] ,STUFF( ( SELECT ','+[Course] FROM [dbo].[SC] WHERE Student = A.Student FOR XML PATH('') ) ,1,1,'' )AS Course FROM [dbo].[SC] AS A
/*拆分字典匹配合並成一行*/ SELECT STUFF( (SELECT ',' + T1.CodeName FROM ( SELECT Code,CodeName from T_ListCode TL JOIN dbo.f_splitstr(T_ST21.Com_FunctionCategory,',') TY ON TL.Code=TY.F1 )AS T1 FOR XML PATH('')),1,1,'') AS CodeName from T_ST21
/*SQL遞歸查詢*/ WITH SearcRiver AS ( SELECT RiverID,UpRiverID FROM T_River WHERE RiverID = '1100000000' UNION ALL SELECT A.RiverID,A.UpRiverID FROM T_River A, SearcRiver B WHERE A.UpRiverID=B.RiverID ) select * from SearcRiver
--try catch 事物-回滾 begin try begin transaction tr select * from Car_Brand update car_log set [reason]='ceshiceshiceshi' where [modelid]=557; select 1/0 print 'i have executed!' select * from AREA print 'executed success'; commit transaction tr end try begin catch print 'executed failed'; rollback transaction tr end catch
查詢執行命令的錯誤信息
函數 | 描述 |
---|---|
ERROR_NUMBER() | 返回導致運行 CATCH 塊的錯誤消息的錯誤號。 |
ERROR_SEVERITY() | 返回導致 CATCH 塊運行的錯誤消息的嚴重級別 |
ERROR_STATE() | 返回導致 CATCH 塊運行的錯誤消息的狀態號 |
ERROR_PROCEDURE() | 返回出現錯誤的存儲過程名稱 |
ERROR_LINE() | 返回發生錯誤的行號 |
ERROR_MESSAGE() | 返回導致 CATCH 塊運行的錯誤消息的完整文本 |
BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRAN --RollBack in case of Error -- you can Raise ERROR with RAISEERROR() Statement including the details of the exception RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1) END CATCH
自定義錯誤
IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name='my_sp_test' AND TYPE='P') BEGIN DROP PROCEDURE my_sp_test; END; GO create procedure my_sp_test @i int, @outstr varchar(100) out as begin try declare @j int; if @i<10 begin set @outstr = 'system exception.'; set @j = 10/0; -- 因為被除數為0,所以這里將會拋出一個系統的異常 end else begin set @j = @i; set @outstr = 'customer exception'; -- 拋出自定義的異常,在最后的catch塊中統一處理異常 RAISERROR (66666, -- Message id. 16, -- Severity, 1 -- State, ) ; end; end try begin catch if @@ERROR=66666 begin -- 通過@@ERROR的值來判斷是否是自定義的異常 set @outstr = @outstr + '---------------- customer exception'; end; return; end catch; go
如上代碼,raiserror參數說明:
(1). Message id : 異常的唯一標識,且這個值會被賦值給SQLServer的系統變量@@Error。自定義異常的Message Id建議使用50000以后的,因為50000以內的會被系統異常占用。
(2). Severity : 異常的級別。 可輸入1—19的數值。1—10之間不會被catch捕獲。19以后是非常嚴重的級別。
(3). State : 如果輸入負值或大於255 的值會生成錯誤,產生錯誤則會中斷數據庫的連接
執行命令,不返回影響行數消息
SET ANSI_NULLS ON
如上代碼,raiserror參數說明:
(1). Message id : 異常的唯一標識,且這個值會被賦值給SQLServer的系統變量@@Error。
自定義異常的Message Id建議使用50000以后的,因為50000以內的會被系統異常占用。
(2). Severity : 異常的級別。 可輸入1—19的數值。1—10之間不會被catch捕獲。19以后是非常嚴重的級別。
(3). State : 如果輸入負值或大於255 的值會生成錯誤,產生錯誤則會中斷數據庫的連接
/*時間范圍交集*/ select * from test_table where (startTime > a AND startTime < b) OR (startTime < a AND endTime > b) OR (endTime > a AND endTime < b)
/*SQL判斷兩個時間段是否有交集 給定時間區間(begin,end),數據庫字段startTime與endTime,*/ SELECT * FROM xxx WHERE NOT ((endTime < begin) OR (startTime > end))
DBCC DROPCLEANBUFFERS --清除緩沖區 DBCC FREEPROCCACHE --刪除計划高速緩存中的元素 SET STATISTICS TIME ON --執行時間 SET STATISTICS IO ON --IO讀取
/*數據庫表碎片整理*/ 通過對掃描密度(過低),掃描碎片(過高)的結果分析,判定是否需要索引重建,主要看如下兩個: Scan Density [Best Count:Actual Count]-掃描密度[最佳值:實際值]:DBCC SHOWCONTIG返回最有用的一個百分比。這是擴展盤區的最佳值和實際值的比率。該百分比應該盡可能靠近100%。低了則說明有外部碎片。 Logical Scan Fragmentation-邏輯掃描碎片:無序頁的百分比。該百分比應該在0%到10%之間,高了則說明有外部碎片。 解決方式: 一是利用DBCC INDEXDEFRAG整理索引碎片 二是利用DBCC DBREINDEX重建索引。 兩者區別調用如下: DBCC INDEXDEFRAG 命令是聯機操作,所以索引只有在該命令正在運行時才可用,而且可以在不丟失已完成工作的情況下中斷該操作。這種方法的缺點是在重新組織數據方面沒有聚集索引的除去/重新創建操作有效。 重新創建聚集索引將對數據進行重新組織,其結果是使數據頁填滿。填滿程度可以使用 FILLFACTOR 選項進行配置。這種方法的缺點是索引在除去/重新創建周期內為脫機狀態,並且操作屬原子級。如果中斷索引創建,則不會重新創建該索引。也就是說,要想獲得好的效果,還是得用重建索引,所以決定重建索引。
/*整理碎片*/ --查找 DBCC SHOWCONTIG('TbName','IDX_TbName') DBCC SHOWCONTIG('TbName','IDX_TbName') --整理 DBCC INDEXDEFRAG([DBName],'TbName','IDX_TbName') DBCC INDEXDEFRAG([DBName],'TbName','IDX_TbName') /*表壓縮*/ alter table TbName rebuild with(data_compression=row) GO SP_SPACEUSED 'TbName' alter table TbName rebuild with(data_compression=row) GO SP_SPACEUSED 'TbName' /*壓縮索引*/ alter index IDX_TbName on TbName rebuild with(data_compression=row) alter index IDX_TbName on TbName rebuild with(data_compression=row) /*整體數據庫收縮*/ use DBName ALTER DATABASE DBName SET RECOVERY SIMPLE;--設置簡單恢復模式 GO DBCC SHRINKFILE (CPLHP3Base_log, 1); GO ALTER DATABASE DBName SET RECOVERY FULL;--恢復為原模式 GO
內連接(inner join)、外連接(outer join)、全連接(full join)、left join 、right join、Cross join
LEFT JOIN (一對多) 左邊主表至少顯示一條數據,需要先過濾再查詢,方式1 ON 關聯 后面加條件,方式2 子查詢過濾;
--Sql Server 添加用戶權限映射已存在 沖突 User DBName sp_change_users_login 'update_one', 'UserName', 'UserName' --添加用戶數據庫owner權限 User DBName exec sp_addrolemember 'db_owner', [UserName]