SQL Server 2005中的存儲過程並發問題
我在SQL Server2005中遇到了並發問題。我持有車票的公共汽車上有一些空閒的座位。我在插入銷售的查票之前,需要查看是否還有空閒的座位。我的存儲過程做的事情如下所示:
CREATE PROCEDURE add_ticket — parameters
DECLARE free_seats int BEGIN TRANSACTION SELECT free_seats
= COUNT(*) FROM tickets WHERE seat_is_not_taken IF free_seats
<> 0 INSERT INTO tickets VALUES(…) — some other statements END TRANSACTION
問題就是兩個過程可以同時讀取空閒票數,並且都可以預約一張票,即使是那裡已經沒有空余的了。我需要一種方法來防止一個過程在另一個過程運行add_ticket程序,但是還沒有插入一張新票的時候讀取空票的數量。
回答:
你是正確的;更高的隔離級別也不會保證多個讀者去同時去讀取同一個數據行。然而,還有幾種方法你可以完成這項工作。例如,你可以給每個座位分配一個惟一的標識符(意思是,惟一鍵——不一定是GUID),並且創建一個描述哪些座位已經被預訂了的表。在表上放一個 UNIQUE約束,你就可以確保同一個座位不會被插入兩次了。
就是說,我認為一個更有趣的方法就是使用SQL Service Broker。你可以為每個公交建立一個會話,並且將這個會話的句柄存放在一個表中,讀者在執行RECEIVE之前可以參考這個表。通過這種方式,讀者就可以正確地過濾。公共汽車上的每個座位都插一個消息到隊列中。讀者就可以簡單地RECEIVE到所需的消息(在這個過程中,預定公共汽車上的座位)。 Service Broker會確保沒有消息會被接受兩次,也就是說你不會再遇到並發問題了。
SQL Server 2005中取代了查詢分析器
回答:
你是對的。查詢分析器和企業管理器都從SQL Server中刪除了。取代它們的是一個工具,SQL Server 管理套件(SQL Server Management Studio)。這個工具具有前任的大多數特性,但是擁有升級後的用戶界面和很多經過改善的功能。我覺得大多數的數據庫管理員都會發現這是一個很好的升級。
如果你想要了解更多有關SQL Server管理套件的新特性的信息,請閱讀SearchSQLServer.com 上有關這個話題的文章。
SQL vs. T-SQL
回答:
SQL是結構化查詢語言,是ANSI/ISO 認可的標准數據庫語言。SQL Server的實現語言叫做Transact-SQL (T-SQL)。T-SQL基本上是根據1992年發表的ISO標准出現的,在1999年的標准上稍加修改。此外,微軟還進行了各種私有的加強。
標准SQL和T-SQL之間有很多區別——太多了,這裡就不說了。還有,如果你在SQL Server上工作,那麼使用這些私有的擴展是有好處的。由於許多SQL Server的特性的本質,你不使用非標准的命令的話,將會有很多強大的功能無法實現。如果你想要看看你的SQL是否符合標准,你可以使用SET FIPS_FLAGGER命令。
SQL Server 2005中是否有新的索引類別了?
回答:
SQL Server 2005沒有為關系表引入新的索引類型。基本上——聚簇和非聚簇索引是以B-trees的方式實現的——還仍然在應用。然而,SQL Server 2005確實包含了一些索引上的加強,不論是完全文本索引,還是對於XML數據,此外這些加強還可以改善一些與關系型索引有關的問題。
SQL Server 2005的完全文本索引特性是全新的,並且是重新編寫的。要獲得這個特性的信息,請閱讀Nimish Khanolkar的MSDN廣播文檔,介紹SQL Server 2005中的全文本查找。
XML是SQL Server 2005中另外一個在方式上發生了巨大轉變的內容。現在對於開發人員來說有第一流的XML數據類型可用了。這個類型支持XQuery查詢語言,使用了這個類型的字段可以通過特殊格式的XML索引被索引到。要了解更多有關XML類型的信息,請查找MSDN 上的文章。
還有各種各樣的有關T-SQL索引命令的加強。也許最令人感興趣的就是新的“在線”索引類型,它允許數據庫管理員在不需要把用戶鎖到表外面的情況下執行索引維護任務。這個很有可能標記著數據庫管理員需要等到夜裡3點才能打開維護窗口修正問題的狀況的終結!要了解更多有關這個特性的信息,請查找SQL Server Worldwide Users Group 上的文章。
為行選擇創建一個腳本
想象一下這個表:
prod_key item_key pack_key last_sale
LM001 1029 AD100 2004/12/05
LM870 1029 AD100 2005/09/20
PE789 1030 BC400 2003/07/12
PE312 1030 BC400 2004/08/07
我想要選出哪些在item_key 和pack_key相等的情況下,日期比較大的那一行。換句話說,我想要:
LM870 1029 AD100 2005/09/20
PE312 1030 BC400 2004/08/07
回答:
這個表有主鍵嗎?那樣的話查詢可能會容易些。不管怎麼樣,我覺得你應該按照下面這樣:
SELECT prod_key,item_key,pack_key,last_sale
FROM (SELECT item_key,pack_key,MAX(last_sale)
AS last_sale FROM tablex GROUP BY item_key,pack_key) AS MaxDateTable
WHERE tablex.item_key = MaxDateTable.item_key
AND tablex.pack_key = MaxDateTable.pack_key
AND tablex.last_sale = MaxDateTable.last_sale
列出沒有記錄的數據庫表
我創建了一個動態的SQL Server查詢來輸出表中行的數量。我的目標是列出在數據庫中沒有記錄的表。查詢如下所示:
declare @strsql varchar(100)
declare @tablename varchar(50)
@tablename=’table123′@strsql=’
select count(*) from ‘ + @tablename exec(@strsql)
我得到了輸出,但是我無法把這個值存儲到變量中以備查看。
B<>我想要這樣查看:
/* @countvariable=0
print(@tablename)*/
還有其它的解決方法嗎?
回答:
你可以讓你的解決方案更加靈活一些,通過從sysobjects表中抓取表名:
declare @strsql varchar(256)
create table #emptytables
(tablename varchar(128), table_rowcount int)select
@strsql=’select distinct o.name as TableName,
.rowcnt as Table_RowCount
from sysobjects o
inner join sysindexes x
on o.id = x.id
where x.rowcnt = 0 and
o.type = ‘’U”’insert #emptytables (TableName,
Table_rowcount) exec (@strsql)
select * from #emptytables
drop table #emptytables