業務需求如下:有表a
,在查詢的時候,需要根據標誌確定是查詢大於某個值的記錄,還是小於某個值的記錄 if
@a = 0
select [trannumber] from a
where [trannumber] < 10000
else
if @a = 1
select [trannumber] from a
where [trannumber] > 10000
select
[trannumber] from a
where
(@a = 0 and [trannumber] < 10000)
or(@a = 1 and [trannumber] > 10000)
從語句的簡捷性來看,方法
b具有技巧性,它們兩者之間,究竟那乙個更好呢?你可能會從效能上來評估,以決定到底用那一種。單純從語句上來看,兩者的效率差別應該不會非常大,實際測試的結果會如我們想象嗎?繼續往下看
declare
@a int
set@a = 0
declare
@t table(
id int
identity,
a int
, b int)
declare
@dt datetime
, @loop int
, @id int
set@loop = 1
while
@loop < 10
begin
set @loop = @loop + 1
raiserror
('test %d'
, 10, 1, @loop)
with nowait
set @dt =
getdate()
if @a = 0
select
*from a
where [trannumber] < 10000
else
if @a = 1
select
*from a
where [trannumber] > 10000
insert @t(a)
values
(datediff
(ms, @dt,
getdate
()))
select @id =
scope_identity
(), @dt =
getdate()
select
*from a
where
(@a = 0 and [trannumber] < 10000) or
(@a = 1 and [trannumber] > 10000)
update @t set b =
datediff
(ms, @dt,
getdate
())
where id = @id
endselect
*from @t
union
all
select
null,
sum(a),
sum(b)
from @t
id a b
----------- ----------- -----------
1 173 173
2 140 170
3 140 173
4 126 170
5 140 173
6 140 173
7 123 170
8 190 170
9 123 190
null 1295 1562
除了效能外,另乙個要考慮的問題是block的問題,下面的測試來反映block的影響
-- run query windows 1
begin
tran
update a set [item] =
right(
newid
(), 4)
where [trannumber] < 100
--rollback tran
-- run query windows 2
declare
@a int
set@a = 1
if@a = 0
select
*from a
where [trannumber] < 10000
else
if @a = 1
select
*from a
where [trannumber] > 10000
-- run query windows 3
declare
@a int
set@a = 1
select
*from a
where
(@a = 0 and [trannumber] < 10000)
or
(@a = 1 and [trannumber] > 10000)
結果
你會看到,查詢視窗
b中的查詢會及時地完成,而查詢視窗
c的查詢會一直等待,你可以通過執行儲存過程
sp_who2
,檢視當前的
block
狀況來確定查詢視窗
c的查詢是否被查詢視窗
a的查詢
block住
usetempdb go
setnocount
on--***********************************=== --
建立測試環境
--***********************************===
raiserror('
建立測試環境',
10, 1)
with nowait
-- table a
create
table [dbo].a(
[trannumber] [int] identity
(1, 1)
notnull,
[invno] [char](8)
notnull,
[item] [char](15)
null
default(''
),primary
key([trannumber]))
create
index [indexoninvno] on [dbo].a([invno])
create
index [indexonitem] on [dbo].a ([item])
create
index [indexoniteminnvo] on [dbo].a([invno], [item])go
--***********************************=== --
生成測試資料
--***********************************===
raiserror('
生成測試資料',
10, 1)
with nowait
insert
[dbo].a([invno], [item])
select
left(
newid
(), 8),
right(
newid
(), 15)
from
syscolumns a, syscolumns b
避免把判斷處理放入 WHERE 條件
問題描述 業務需求如下 有表a,在查詢的時候,需要根據標誌確定是查詢大於某個值的記錄,還是小於某個值的記錄 a 一般的處理方法 if a 0 select trannumber from a where trannumber 10000 else if a 1 select trannumber f...
避免把判斷處理放入 WHERE 條件
問題描述 業務需求如下 有表a,在查詢的時候,需要根據標誌確定是查詢大於某個值的記錄,還是小於某個值的記錄 a 一般的處理方法 if a 0 select trannumber from a where trannumber 10000 else if a 1 select trannumber f...
把SQL Server放入保險箱
安全模式簡介 從系統結構上來講sql server有兩種安全模式。第一種是 僅windows 模式,這種模式只允許擁有受信任的windows nt賬戶的使用者登入,是sql server預設的安全模式,也是較安全的選項,使用者登入sql server的前提是該使用者使用windows nt的域賬戶登...