SQL Server開發(fā)過程中的的常見問題總結(jié)
在SQL Server開發(fā)問題中你可能會問到的十個問題:
1、什么是常見的對表和字段的名字約束?
2、有沒有可能在不了解T-SQL的情況下編寫存儲過程?
3、T-SQL 中如何比較CLR 存儲過程和函數(shù)的性能?
4、我如何在一個存儲過程中使用另一個存儲過程產(chǎn)生的結(jié)果?
5、我如何解決SQL Server 2005的并發(fā)問題?
6、在SQL Server 2005中用什么工具替代了查詢分析器?
7、你能提供一些有關(guān)SQL 和T-SQL的詳細(xì)信息嗎?
8、SQL Server 2005 有沒有新的索引類型?
9、我如何創(chuàng)建一個腳本在表中進行選擇?
10、我如何列出那些沒有記錄的數(shù)據(jù)庫表?
對于表和字段的常見名字約束
回答:
SQL Server 2000下的表和字段名稱有1到128字節(jié)的限制,并且遵循用于標(biāo)識的規(guī)則。
第一個字母必須是如下的一種:
· Unicode Standard 2.0中規(guī)定的字母。
Unicode對字母的定義包括:拉丁字母,從A到Z,除了來自其他語言的字母之外。
· 下劃線(_),at符號(@),或者數(shù)字符號(#)
在SQL Server中以這些符號作為標(biāo)識符的開始具有特殊的含義。一個以at符號(@)開頭的標(biāo)識符表示一個本地的變量或者參數(shù)。一個以數(shù)字符號(#)開頭的標(biāo)識符代表一個臨時表或者過程。一個以兩個數(shù)字符號(##)開頭的標(biāo)識符標(biāo)識的是一個全局臨時對象。
一些Transact-SQL函數(shù)的名字以兩個at符號(@@)開頭。為了避免與這些函數(shù)混淆,推薦你不要使用兩個at符號(@@)開頭的標(biāo)識符。
接下來的字母可以是以下的任意幾種:
· Unicode Standard 2.0定義的字母
· 來自基礎(chǔ)拉丁文或者其他語音的十進制數(shù)字
· at符號(@),美元符號($),數(shù)字符號(#),或者下劃線
標(biāo)識符絕對不能是Transact-SQL的保留字。SQL Server保留了一些大寫和小寫的保留字。內(nèi)建的空間或者特殊的字母都不允許出現(xiàn),盡管你可以在好的老版本的Northwind中看到它們包含了內(nèi)建的空間。你必須通過把它們括在括號中才可以訪問。
不具有任何T-SQL知識的情況下編寫SQL Server2005存儲過程嗎?
許多程序員都認(rèn)為創(chuàng)建SQL Server存儲過程不再必需T-SQL了。不幸的是(或者并非如此,這根據(jù)你的觀點),這并不全是事實。在技術(shù)上是可以在不了解T-SQL的情況下創(chuàng)建存儲過程的,但是沒有T-SQL的話則無法訪問任何的數(shù)據(jù)。
在CLR存儲過程內(nèi)部進行數(shù)據(jù)訪問,是通過使用標(biāo)準(zhǔn)的ADO.NET類來完成的。開發(fā)人員會在應(yīng)用程序?qū)影l(fā)現(xiàn)很多同樣的沒有用處的數(shù)據(jù)訪問代碼,這些代碼會很輕易地轉(zhuǎn)移到SQLCLR例程中去。當(dāng)中間層的這些ADO.NET類需要使用T-SQL來訪問數(shù)據(jù)的時候,在 CLR主機提供的環(huán)境中就會使用同樣的類。
我要強調(diào)的是,從技術(shù)角度來說,不使用T-SQL來編寫存儲過程是可能的。那么有沒有理由這么做呢?一種情況就是這是一個用來從普通文件或者網(wǎng)絡(luò)服務(wù)中檢索數(shù)據(jù)的CLR存儲過程,并將數(shù)據(jù)格式設(shè)置為行集。這里可能就會用到不需要T-SQL的操作——但是這并不是對T -SQL存儲過程能力的一個很好的比喻。
CLR存儲過程vs. T-SQL存儲過程
CLR存儲過程和函數(shù)與T-SQL存儲過程和函數(shù)相比,性能如何?
回答:
這里是用來比較T-SQL例程和CLR例程性能的一種常用的規(guī)則:用你的數(shù)據(jù),在你的服務(wù)器上,測試兩套配置,看看哪一個比較好。
就是說,許多人都運行過性能測試,一般的結(jié)果就是T-SQL在標(biāo)準(zhǔn)的CRUD(創(chuàng)建、讀取、更新、刪除)操作上表現(xiàn)要比好一點,而在復(fù)雜數(shù)學(xué)、字符串賦值和其他的超過數(shù)據(jù)訪問的任務(wù)上,則是CLR的性能表現(xiàn)更好一點。
SQL Server 的專家Gustavo Larriera編輯了如下一些關(guān)于這個主題的有用鏈接:
·在 SQL Server 2005中使用CLR Integration。
·簡單介紹在 SQL Server 2005中的 CLR Integration。
·在 SQL Server 2005中對CLR 和T-SQL做出選擇。
·介紹 SQL Server 2005中的 CLR Integration。
·SQL Server 閑談: SQL Server 2005 Beta 2 CLR問題與回答。
·數(shù)據(jù)庫管理員的防御.NET。
·用戶自定義函數(shù)的性能比較。
如何在一個存儲過程中使用另一個存儲過程的結(jié)果?
專家回答:
只要存儲過程只產(chǎn)生了一個單個的結(jié)果,要在另外一個存儲過程中使用這個存儲過程產(chǎn)生的輸出,這個技術(shù)是非常直接的。這個技術(shù)就是使用一個臨時表來裝載存儲過程的巨額iguo,然后通過INSERT EXEC語句來執(zhí)行這個過程并保存結(jié)果。一旦結(jié)果保留在臨時表中了,他們就可以像使用其它表數(shù)據(jù)一樣來使用它了。
這里是我們可能會復(fù)用的一個過程例子:
CREATE PROC usp_Demo_AllAuthors as
select * from pubs..authors
GO
現(xiàn)在有一個存儲過程使用usp_Demo_AllAuthors的結(jié)果:
CREATE proc usp_Demo_SPUser as CREATE TABLE #Authors (
au_id varchar(11) NOT NULL PRIMARY KEY CLUSTERED,
au_lname varchar (40) NOT NULL ,
au_fname varchar (20) NOT NULL ,
phone char (12) NOT NULL,
address varchar (40) NULL ,
city varchar (20) NULL ,
state char (2) NULL ,
zip char (5) NULL ,
contract bit NOT NULL
)– Execute usp_Demo_AllAuthors storing the
– results in #Authors
insert into #Authors
exec usp_Demo_AllAuthors– Here we use the #Authors table. This example only
– only selects from the temp table but you could do much
– more such as use a cursor on the table or join with
– other data.
SELECT au_fName + ‘ ‘ + au_lname as [name]
, address+’, ‘+city+’, ‘+state+’ ‘+zip [Addr]
from #AuthorsDROP TABLE #Authors
GO
SQL Server 2005中的存儲過程并發(fā)問題
我在SQL Server2005中遇到了并發(fā)問題。我持有車票的公共汽車上有一些空閑的座位。我在插入銷售的查票之前,需要查看是否還有空閑的座位。我的存儲過程做的事情如下所示:
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
問題就是兩個過程可以同時讀取空閑票數(shù),并且都可以預(yù)約一張票,即使是那里已經(jīng)沒有空余的了。我需要一種方法來防止一個過程在另一個過程運行add_ticket程序,但是還沒有插入一張新票的時候讀取空票的數(shù)量。
回答:
你是正確的;更高的隔離級別也不會保證多個讀者去同時去讀取同一個數(shù)據(jù)行。然而,還有幾種方法你可以完成這項工作。例如,你可以給每個座位分配一個惟一的標(biāo)識符(意思是,惟一鍵——不一定是GUID),并且創(chuàng)建一個描述哪些座位已經(jīng)被預(yù)訂了的表。在表上放一個 UNIQUE約束,你就可以確保同一個座位不會被插入兩次了。
就是說,我認(rèn)為一個更有趣的方法就是使用SQL Service Broker。你可以為每個公交建立一個會話,并且將這個會話的句柄存放在一個表中,讀者在執(zhí)行RECEIVE之前可以參考這個表。通過這種方式,讀者就可以正確地過濾。公共汽車上的每個座位都插一個消息到隊列中。讀者就可以簡單地RECEIVE到所需的消息(在這個過程中,預(yù)定公共汽車上的座位)。 Service Broker會確保沒有消息會被接受兩次,也就是說你不會再遇到并發(fā)問題了。
SQL Server 2005中取代了查詢分析器
回答:
你是對的。查詢分析器和企業(yè)管理器都從SQL Server中刪除了。取代它們的是一個工具,SQL Server 管理套件(SQL Server Management Studio)。這個工具具有前任的大多數(shù)特性,但是擁有升級后的用戶界面和很多經(jīng)過改善的功能。我覺得大多數(shù)的數(shù)據(jù)庫管理員都會發(fā)現(xiàn)這是一個很好的升級。
如果你想要了解更多有關(guān)SQL Server管理套件的新特性的信息,請閱讀SearchSQLServer.com 上有關(guān)這個話題的文章。
SQL vs. T-SQL
回答:
SQL是結(jié)構(gòu)化查詢語言,是ANSI/ISO 認(rèn)可的標(biāo)準(zhǔn)數(shù)據(jù)庫語言。SQL Server的實現(xiàn)語言叫做Transact-SQL (T-SQL)。T-SQL基本上是根據(jù)1992年發(fā)表的ISO標(biāo)準(zhǔn)出現(xiàn)的,在1999年的標(biāo)準(zhǔn)上稍加修改。此外,微軟還進行了各種私有的加強。
標(biāo)準(zhǔn)SQL和T-SQL之間有很多區(qū)別——太多了,這里就不說了。還有,如果你在SQL Server上工作,那么使用這些私有的擴展是有好處的。由于許多SQL Server的特性的本質(zhì),你不使用非標(biāo)準(zhǔn)的命令的話,將會有很多強大的功能無法實現(xiàn)。如果你想要看看你的SQL是否符合標(biāo)準(zhǔn),你可以使用SET FIPS_FLAGGER命令。
SQL Server 2005中是否有新的索引類別了?
回答:
SQL Server 2005沒有為關(guān)系表引入新的索引類型?;旧稀鄞睾头蔷鄞厮饕且訠-trees的方式實現(xiàn)的——還仍然在應(yīng)用。然而,SQL Server 2005確實包含了一些索引上的加強,不論是完全文本索引,還是對于XML數(shù)據(jù),此外這些加強還可以改善一些與關(guān)系型索引有關(guān)的問題。
SQL Server 2005的完全文本索引特性是全新的,并且是重新編寫的。要獲得這個特性的信息,請閱讀Nimish Khanolkar的MSDN廣播文檔,介紹SQL Server 2005中的全文本查找。
XML是SQL Server 2005中另外一個在方式上發(fā)生了巨大轉(zhuǎn)變的內(nèi)容。現(xiàn)在對于開發(fā)人員來說有第一流的XML數(shù)據(jù)類型可用了。這個類型支持XQuery查詢語言,使用了這個類型的字段可以通過特殊格式的XML索引被索引到。要了解更多有關(guān)XML類型的信息,請查找MSDN 上的文章。
還有各種各樣的有關(guān)T-SQL索引命令的加強。也許最令人感興趣的就是新的“在線”索引類型,它允許數(shù)據(jù)庫管理員在不需要把用戶鎖到表外面的情況下執(zhí)行索引維護任務(wù)。這個很有可能標(biāo)記著數(shù)據(jù)庫管理員需要等到夜里3點才能打開維護窗口修正問題的狀況的終結(jié)!要了解更多有關(guān)這個特性的信息,請查找SQL Server Worldwide Users Group 上的文章。
為行選擇創(chuàng)建一個腳本
想象一下這個表:
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
回答:
這個表有主鍵嗎?那樣的話查詢可能會容易些。不管怎么樣,我覺得你應(yīng)該按照下面這樣:
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
列出沒有記錄的數(shù)據(jù)庫表
我創(chuàng)建了一個動態(tài)的SQL Server查詢來輸出表中行的數(shù)量。我的目標(biāo)是列出在數(shù)據(jù)庫中沒有記錄的表。查詢?nèi)缦滤?
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
