在程式設計過程中,經常會遇到需要根據使用者的選擇進行查詢的情況,這時,使用者不同的選擇可能需要查詢不同的表名,而且這個表名可能還不宜事先在程式中定死,需要能動態的隨機選擇。當然還包括表名和使用者的某些資訊相關,可能不同的使用者需要進入不同的表,甚至表名的一部分就是使用者名稱的一部分,等等。對於這些情況,我是使用exec語句進行動態甚至動態跨伺服器進行查詢。我記得剛開始學習sql語句的時候花了不少時間來找方法,現在將這個方法記下來和有興趣的人共同分享。
例程如下:
declare @table varchar(50)
set @table = 'dbo.mfg_shopcal'
exec ('select top 100 * from
' + @table + ' where year(caldate)=2008 and month(caldate)=5')
這裡主要是使用了execute(可以簡寫成exec)語句。這個語句功能十分強大,利用它可以在其他程式中隨意構建sql語句,增加了程式的靈活性。
exec的主要作用是執行 transact-sql 批中的命令字串、字串或執行下列模組之一:系統儲存過程、使用者定義儲存過程、標量值使用者定義函式或擴充套件儲存過程。
sql server 2005 擴充套件了 execute 語句,以使其可用於向鏈結伺服器傳送傳遞命令。此外,還可以顯式設定執行字串或命令的上下文。
exec的語句規則如下:
execute a stored procedure or function[ ]
[ [ @parameter = ]
][ ,...n ]
[ with recompile ]
}[;]execute a character string
( [ + ...n ] )
[ as = ' name ' ]
[;]execute a pass-through command against a linked server
( [ + ...n ]
[ } [...n] ]
) [ as = ' name ' ]
[ at linked_server_name ]
[;]引數
@return_status
可選的整型變數,儲存模組的返回狀態。這個變數在用於 execute 語句前,必須在批處理、儲存過程或函式中宣告過。
在用於呼叫標量值使用者定義函式時,@return_status變數可以是任何標量資料型別module_name
是要呼叫的儲存過程或標量值使用者定義函式的完全限定或者不完全限定名稱。模組名稱必須符合識別符號規則。無論伺服器的排序規則如何,擴充套件儲存過程的名稱總是區分大小寫。
使用者可以執行在另一資料庫中建立的模組,只要執行模組的使用者擁有此模組或具有在該資料庫中執行該模組的適當許可權。使用者可以在另一台執行 sql server 的伺服器中執行模組,只要該使用者有相應的許可權使用該伺服器(遠端訪問),並能在資料庫中執行該模組。如果指定了伺服器名稱但沒有指定資料庫名稱,則sql server 2005 database engine會在使用者的預設資料庫中查詢該模組。
;number
是可選整數,用於對同名的過程分組。該引數不能用於擴充套件儲存過程。
注意後續版本的microsoft sql server將刪除該功能。請避免在新的開發工作中使用該功能,並應著手修改當前還在使用該功能的應用程式。
@module_name_var
是區域性定義的變數名,代表模組名稱。
@parameter
module_name的引數,與在模組中定義的相同。引數名稱前必須加上符號 。
在使用@parameter_name=value 格式時,引數名稱和常量不必按在模組中定義的順序提供。但是,如果任何引數使用了 @parameter_name=value 格式,則對後續的所有引數均必須使用該格式。
預設情況下,引數可為空。如果傳遞null引數值,且該引數用於create 或alter table 語句,由於在這些語句中引用的列不允許為 null值(例如,插入到不允許為null 的列),資料庫引擎就會引發錯誤。為避免將null引數值傳遞給不允許為 null的列,可以在模組中新增程式設計邏輯或使用該列的預設值(使用 create或alter table語句中的default 關鍵字
value
傳遞給模組或傳遞命令的引數值。如果引數名稱沒有指定,引數值必須以在模組中定義的順序提供。
對鏈結伺服器執行傳遞命令時,引數值的順序取決於鏈結伺服器的ole db 訪問介面。大多數ole db訪問介面按從左到右的順序將值繫結到引數。
如果引數值是乙個物件名稱、字串或由資料庫名稱或架構名稱限定,則整個名稱必須用單引號括起來。如果引數值是乙個關鍵字,則該關鍵字必須用雙引號括起來。
如果在模組中定義了預設值,使用者執行該模組時可以不必指定引數。
預設值也可以為null。通常,模組定義會指定當引數值為 null 時應該執行的操作。
@variable
是用來儲存引數或返回引數的變數
output
指定模組或命令字串返回乙個引數。該模組或命令字串中的匹配引數也必須已使用關鍵字 output建立。使用游標變數作為引數時使用該關鍵字。
如果value 定義為對鏈結伺服器執行的模組的output,則ole db 訪問介面對相應@parameter 所執行的任何更改都將在模組執行結束時複製回該變數。
如果使用output 引數,目的是在呼叫批處理或模組的其他語句中使用其返回值,則引數值必須作為變數傳遞,如 @parameter = @variable。如果乙個引數在模組中沒有定義為output 引數,則不能通過對該引數指定 output 執行模組。不能使用output 將常量傳遞給模組;返回引數需要變數名稱。在執行過程之前,必須宣告變數的資料型別並賦值。
當對遠端儲存過程使用execute或對鏈結伺服器執行傳遞命令時,output 引數不能是任何大型物件(lob) 資料型別。
返回引數可以是 lob 資料型別之外的任意資料型別。
default
根據模組的定義,提供引數的預設值。當模組需要的引數值沒有定義預設值並且缺少引數或指定了default 關鍵字,會出現錯誤。
with recompile
執行模組後,強制編譯、使用和放棄新計畫。如果該模組存在現有查詢計畫,則該計畫將保留在快取中。
如果所提供的引數為非典型引數或者資料有很大的改變,使用該選項。該選項不能用於擴充套件儲存過程。建議盡量少使用該選項,因為它消耗較多系統資源。
@string_variable
是區域性變數的名稱。
@string_variable 可以是任意char、varchar、nchar 或 nvarchar資料型別。其中包括(max) 資料型別。
[n] 'tsql_string'
常量字串。tsql_string 可以是任意 nvarchar 或varchar 資料型別。如果包含n,則字串將解釋為nvarchar資料型別。
as <?xml:namespace prefix = o />
指定執行語句的上下文。有關詳細資訊,請參閱了解執行上下文。
login 指定要模擬的上下文是登入名。模擬範圍為伺服器。 user 指定要模擬的上下文是當前資料庫中的使用者。模擬範圍只限於當前資料庫。對資料庫使用者的上下文切換不會繼承該使用者的伺服器級別許可權. 重要事項: 當到資料庫使用者的上下文切換處於活動狀態時,任何對資料庫外部資源的訪問嘗試都會導致語句失敗。這包括 use database 語句、分布式查詢和使用三部分或四部分識別符號引用其他資料庫的查詢。若要將上下文切換的範圍擴充套件到當前資料庫之外,請參閱使用execute as 擴充套件資料庫模擬。 'name' 有效使用者或登入名。name 必須是 sysadmin 固定伺服器角色成員或分別為sys.database_principals或sys.server_principals的主體。 name 不能為內建帳戶,如 nt authority\localservice、nt authority\networkservice 或nt authority\localsystem。 [n] 'command_string' 常量字串,包含要傳遞給鏈結伺服器的命令。如果包含n,則字串將解釋為nvarchar 資料型別。 at linked_server_name 指定對linked_server_name 執行command_string,並將結果(如果有)返回客戶端。linked_server_name 必須引用本地伺服器中的現有鏈結伺服器定義。鏈結伺服器使用sp_addlinkedserver定義。
SQL實現表的動態查詢
一 事例 如果對乙個大學生三年成績的查詢通過學生學號,學生成績按學期存放在不同的表中,成績表如下 cjxx20051 也就是存放學生2005年第一學期的成績 cjxx20052 也就是存放學生2005年第二學期的成績 cjxx20061 也就是存放學生2005年第一學期的成績 cjxx20062 也...
sql動態查詢
所以我有乙個從網頁傳遞的dict。我想基於dict動態構建查詢。我知道我可以做 session.query myclass filter by web dict 但是,僅當值完全匹配時才起作用。我需要做 像 過濾。我最好的嘗試使用 dict 屬性 for k,v in web dict.items ...
MyBatis動態sql查詢
什麼是動態sql mybatis核心 對sql語句進行靈活操作,通過表示式進行判斷,對sql進行靈活拼接 組裝。需求public class userpo if test userpo.id null and id if if where select id findusercount parame...