過程
- SQLserver 過程是具有特定功能,可多次對數據表操作的獨立模塊。
- 返回值通常用return 返回整數 0,1…。(可選)
- 也可通過output 參數或select 語句返回結果集。
1.過程的定義
本過程定義了一個過程,輸入一個動態SQL語句,將結果行集組成一個SQL命令串,返回結果。該過程使用Function 是不能完成的。
CREATE PROCEDURE [dbo].[getCmd]@CursorStr nvarchar(max),@Str nvarchar(max)='' out
as
beginset nocount on;declare @s nvarchar(max)='';set @CursorStr=' declare Cur cursor for '+@CursorStr;exec sp_executeSql @CursorStr;open Cur;FETCH NEXT FROM Cur INTO @s;WHILE @@FETCH_STATUS = 0BEGINSET @Str=@Str+@s;FETCH NEXT FROM Cur INTO @s; endclose Cur;--關閉標量庫deallocate Cur;--釋放光標空間 return 0;
end
2.過程的調用
DECLARE @IndexSQL NVARCHAR(MAX);
declare @ic nvarchar(max);
set @ic=@oldDb+'.sys.index_columns';
--declare @c nvarchar(max);
set @c=@oldDb+'.sys.columns';
declare @i nvarchar(max);
set @i=@oldDb+'.sys.indexes';
--declare @t nvarchar(max);
set @t=@oldDb+'.sys.tables';
SET @IndexSQL = '';
set @cmd='
SELECT ''CREATE '' + CASE WHEN i.is_unique = 1 THEN ''UNIQUE '' ELSE '''' END + i.type_desc + '' INDEX '' + QUOTENAME(i.name) + '' ON '+@newDb+'.dbo.'' + QUOTENAME(t.name) + '' ('' + STUFF((SELECT '', '' + QUOTENAME(c.name)FROM '+@ic+' icJOIN '+@c+' c ON ic.column_id = c.column_id AND ic.object_id = c.object_idWHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0ORDER BY ic.key_ordinalFOR XML PATH(''''), TYPE).value(''.'', ''NVARCHAR(MAX)''), 1, 2, '''') + '')'' + CASE WHEN EXISTS (SELECT *FROM '+@ic+' icJOIN zwdb.sys.columns c ON ic.column_id = c.column_id AND ic.object_id = c.object_idWHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 1) THEN '' INCLUDE ('' + STUFF((SELECT '', '' + QUOTENAME(c.name)FROM '+@ic+' icJOIN '+@c+' c ON ic.column_id = c.column_id AND ic.object_id = c.object_idWHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 1ORDER BY ic.index_column_idFOR XML PATH(''''), TYPE).value(''.'', ''NVARCHAR(MAX)''), 1, 2, '''') + '')'' ELSE '''' END + '';'' + CHAR(13) + CHAR(10) COLLATE Chinese_PRC_CI_AS AS combined_column
FROM '+@i+' i
JOIN '+@t+' t ON i.object_id = t.object_id
WHERE i.is_primary_key = 0 AND i.is_unique_constraint = 0 AND t.is_ms_shipped = 0 AND i.index_id > 0;';
exec zwdb.dbo.getCmd @CursorStr=@cmd,@Str=@IndexSQL output ;
IF @IndexSQL <> ''EXEC sp_executesql @IndexSQL;
總結
1. 數據修改能力
(1)標量函數:
- 不允許修改數據(如 INSERT、UPDATE、DELETE)。
- 只能讀取數據,保持函數的確定性(相同輸入始終返回相同輸出)。
(2)存儲過程:
- 允許修改數據,支持事務處理(如 BEGIN TRANSACTION)。
- 可執行任何 T-SQL 語句,包括動態 SQL。
2. 性能與優化
(1)標量函數:
- 性能較低,尤其在 WHERE 子句中頻繁調用時,可能導致全表掃描。
- 適合簡單計算,避免復雜邏輯。
(2)存儲過程:
- 性能較高,執行計劃可緩存,減少編譯開銷。
- 適合復雜業務邏輯(如批量數據處理)。
3. 應用場景
(1)標量函數:
- 數據計算(如格式化日期、字符串處理)。
- 在查詢中作為表達式使用(如 SELECT、JOIN 條件)。
(2)存儲過程:
- 業務邏輯封裝(如用戶認證、訂單處理)。
- 數據修改操作(如批量插入、事務處理)。
- 跨數據庫操作或調用外部資源(如調用 API)。
4. 其他差異
特性 | 標量函數 | 存儲過程 |
---|---|---|
事務支持 | 不支持 | 支持(可使用 BEGIN TRANSACTION) |
動態 SQL | 不允許 | 允許 |
權限控制 | 可通過 GRANT EXECUTE 授權 | 同上 |
在視圖中使用 | 允許 | 不允許(視圖中不能直接調用存儲過程) |
結果集返回 | 不支持(只能返回單個值) | 支持(通過 SELECT 語句) |
總結
場景 | 推薦使用標量函數 | 推薦使用存儲過程 |
---|---|---|
簡單計算(如數學公式) | ? | ? |
查詢中作為表達式 | ? | ? |
數據修改(INSERT/UPDATE) | ? | ? |
復雜業務邏輯 | ? | ? |
事務處理 | ? | ? |
動態 SQL | ? | ? |
建議:
優先使用存儲過程處理業務邏輯,使用標量函數處理簡單計算,避免在大型數據集上頻繁調用函數。