天天看點

存儲過程文法及執行個體

存儲過程如同一門程式設計語言,同樣包含了資料類型、流程控制、輸入和輸出和它自己的函數庫。

--------------------基本文法--------------------

一.建立存儲過程

create procedure sp_name()

begin

.........

end

二.調用存儲過程

1.基本文法:call sp_name()

注意:存儲過程名稱後面必須加括号,哪怕該存儲過程沒有參數傳遞

三.删除存儲過程

1.基本文法:

drop procedure sp_name//

2.注意事項

(1)不能在一個存儲過程中删除另一個存儲過程,隻能調用另一個存儲過程

四.其他常用指令

1.show procedure status

顯示資料庫中所有存儲的存儲過程基本資訊,包括所屬資料庫,存儲過程名稱,建立時間等

2.show create procedure sp_name

顯示某一個mysql存儲過程的詳細資訊

--------------------資料類型及運算符--------------------

一、基本資料類型:

二、變量:

自定義變量:DECLARE   a INT ; SET a=100;    可用以下語句代替:DECLARE a INT DEFAULT 100;

變量分為使用者變量和系統變量,系統變量又分為會話和全局級變量

使用者變量:使用者變量名一般以@開頭,濫用使用者變量會導緻程式難以了解及管理

1、 在mysql用戶端使用使用者變量

mysql> SELECT 'Hello World' into @x;

mysql> SELECT @x;

mysql> SET @y='Goodbye Cruel World';

mysql> select @y;

mysql> SET @z=1+2+3;

mysql> select @z;

2、 在存儲過程中使用使用者變量

mysql> CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');

mysql> SET @greeting='Hello';

mysql> CALL GreetWorld( );

3、 在存儲過程間傳遞全局範圍的使用者變量

mysql> CREATE PROCEDURE p1( )   SET @last_procedure='p1';

mysql> CREATE PROCEDURE p2( ) SELECT CONCAT('Last procedure was ',@last_procedure);

mysql> CALL p1( );

mysql> CALL p2( );

三、運算符:

1.算術運算符

+     加   SET var1=2+2;       4

-     減   SET var2=3-2;       1

*      乘   SET var3=3*2;       6

/     除   SET var4=10/3;      3.3333

DIV   整除 SET var5=10 DIV 3; 3

%     取模 SET var6=10%3 ;     1

2.比較運算符

>            大于 1>2 False

<            小于 2<1 False

<=           小于等于 2<=2 True

>=           大于等于 3>=2 True

BETWEEN      在兩值之間 5 BETWEEN 1 AND 10 True

NOT BETWEEN 不在兩值之間 5 NOT BETWEEN 1 AND 10 False

IN           在集合中 5 IN (1,2,3,4) False

NOT IN       不在集合中 5 NOT IN (1,2,3,4) True

=             等于 2=3 False

<>, !=       不等于 2<>3 False

<=>          嚴格比較兩個NULL值是否相等 NULL<=>NULL True

LIKE          簡單模式比對 "Guy Harrison" LIKE "Guy%" True

REGEXP       正則式比對 "Guy Harrison" REGEXP "[Gg]reg" False

IS NULL      為空 0 IS NULL False

IS NOT NULL 不為空 0 IS NOT NULL True

3.邏輯運算符

4.位運算符

|   或

&   與

<< 左移位

>> 右移位

~   非(單目運算,按位取反)

注釋:

mysql存儲過程可使用兩種風格的注釋

雙橫杠:--

該風格一般用于單行注釋

c風格:/* 注釋内容 */ 一般用于多行注釋

--------------------流程控制--------------------

一、順序結構

二、分支結構

if

case

三、循環結構

for循環

while循環

loop循環

repeat until循環

注:

區塊定義,常用

......

end;

也可以給區塊起别名,如:

lable:begin

...........

end lable;

可以用leave lable;跳出區塊,執行區塊以後的代碼

begin和end如同C語言中的{ 和 }。

--------------------輸入和輸出--------------------

mysql存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT

Create procedure|function([[IN |OUT |INOUT ] 參數名 資料類形...])

IN 輸入參數

表示該參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被傳回,為預設值

OUT 輸出參數

該值可在存儲過程内部被改變,并可傳回

INOUT 輸入輸出參數

調用時指定,并且可被改變和傳回

IN參數例子:

CREATE PROCEDURE sp_demo_in_parameter(IN p_in INT)

BEGIN

SELECT p_in; --查詢輸入參數

SET p_in=2; --修改

select p_in;--檢視修改後的值

END;

執行結果:

mysql> set @p_in=1

mysql> call sp_demo_in_parameter(@p_in)

mysql> select @p_in;

以上可以看出,p_in雖然在存儲過程中被修改,但并不影響@p_id的值

OUT參數例子

建立:

mysql> CREATE PROCEDURE sp_demo_out_parameter(OUT p_out INT)

SELECT p_out;/*檢視輸出參數*/

SET p_out=2;/*修改參數值*/

SELECT p_out;/*看看有否變化*/

mysql> SET @p_out=1

mysql> CALL sp_demo_out_parameter(@p_out)

mysql> SELECT @p_out;

INOUT參數例子:

mysql> CREATE PROCEDURE sp_demo_inout_parameter(INOUT p_inout INT)

SELECT p_inout;

SET p_inout=2;

執行結果:

set @p_inout=1

call sp_demo_inout_parameter(@p_inout) //

select @p_inout;

附:函數庫

mysql存儲過程基本函數包括:字元串類型,數值類型,日期類型

一、字元串類

CHARSET(str) //傳回字串字元集

CONCAT (string2 [,… ]) //連接配接字串

INSTR (string ,substring ) //傳回substring首次在string中出現的位置,不存在傳回0

LCASE (string2 ) //轉換成小寫

LEFT (string2 ,length ) //從string2中的左邊起取length個字元

LENGTH (string ) //string長度

LOAD_FILE (file_name ) //從檔案讀取内容

LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定開始位置

LPAD (string2 ,length ,pad ) //重複用pad加在string開頭,直到字串長度為length

LTRIM (string2 ) //去除前端空格

REPEAT (string2 ,count ) //重複count次

REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替換search_str

RPAD (string2 ,length ,pad) //在str後用pad補充,直到長度為length

RTRIM (string2 ) //去除後端空格

STRCMP (string1 ,string2 ) //逐字元比較兩字串大小,

SUBSTRING (str , position [,length ]) //從str的position開始,取length個字元,

注:mysql中處理字元串時,預設第一個字元下标為1,即參數position必須大于等于1

mysql> select substring(’abcd’,0,2);

+———————–+

| substring(’abcd’,0,2) |

|                       |

1 row in set (0.00 sec)

mysql> select substring(’abcd’,1,2);

| substring(’abcd’,1,2) |

| ab                    |

1 row in set (0.02 sec)

TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字元

UCASE (string2 ) //轉換成大寫

RIGHT(string2,length) //取string2最後length個字元

SPACE(count) //生成count個空格

二、數值類型

ABS (number2 ) //絕對值

BIN (decimal_number ) //十進制轉二進制

CEILING (number2 ) //向上取整

CONV(number2,from_base,to_base) //進制轉換

FLOOR (number2 ) //向下取整

FORMAT (number,decimal_places ) //保留小數位數

HEX (DecimalNumber ) //轉十六進制

注:HEX()中可傳入字元串,則傳回其ASC-11碼,如HEX(’DEF’)傳回4142143

也可以傳入十進制整數,傳回其十六進制編碼,如HEX(25)傳回19

LEAST (number , number2 [,..]) //求最小值

MOD (numerator ,denominator ) //求餘

POWER (number ,power ) //求指數

RAND([seed]) //随機數

ROUND (number [,decimals ]) //四舍五入,decimals為小數位數]

注:傳回類型并非均為整數,如:

(1)預設變為整形值

mysql> select round(1.23);

+————-+

| round(1.23) |

|           1 |

mysql> select round(1.56);

| round(1.56) |

|           2 |

(2)可以設定小數位數,傳回浮點型資料

mysql> select round(1.567,2);

+—————-+

| round(1.567,2) |

|           1.57 |

SIGN (number2 ) //傳回符号,正負或0

SQRT(number2) //開平方

三、日期類型

ADDTIME (date2 ,time_interval ) //将time_interval加到date2

CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //轉換時區

CURRENT_DATE ( ) //目前日期

CURRENT_TIME ( ) //目前時間

CURRENT_TIMESTAMP ( ) //目前時間戳

DATE (datetime ) //傳回datetime的日期部分

DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或時間

DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式顯示datetime

DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上減去一個時間

DATEDIFF (date1 ,date2 ) //兩個日期差

DAY (date ) //傳回日期的天

DAYNAME (date ) //英文星期

DAYOFWEEK (date ) //星期(1-7) ,1為星期天

DAYOFYEAR (date ) //一年中的第幾天

EXTRACT (interval_name FROM date ) //從date中提取日期的指定部分

MAKEDATE (year ,day ) //給出年及年中的第幾天,生成日期串

MAKETIME (hour ,minute ,second ) //生成時間串

MONTHNAME (date ) //英文月份名

NOW ( ) //目前時間

SEC_TO_TIME (seconds ) //秒數轉成時間

STR_TO_DATE (string ,format ) //字串轉成時間,以format格式顯示

TIMEDIFF (datetime1 ,datetime2 ) //兩個時間差

TIME_TO_SEC (time ) //時間轉秒數]

WEEK (date_time [,start_of_week ]) //第幾周

YEAR (datetime ) //年份

DAYOFMONTH(datetime) //月的第幾天

HOUR(datetime) //小時

LAST_DAY(date) //date的月的最後日期

MICROSECOND(datetime) //微秒

MONTH(datetime) //月

MINUTE(datetime) //分

注:可用在INTERVAL中的類型:DAY ,DAY_HOUR ,DAY_MINUTE ,DAY_SECOND ,HOUR ,HOUR_MINUTE ,HOUR_SECOND ,MINUTE ,MINUTE_SECOND,MONTH ,SECOND ,YEAR

DECLARE variable_name [,variable_name...] datatype [DEFAULT value]; 

其中,datatype為mysql的資料類型,如:INT, FLOAT, DATE, VARCHAR(length)

例:

DECLARE l_int INT unsigned default 4000000; 

DECLARE l_numeric NUMERIC(8,2) DEFAULT 9.95; 

DECLARE l_date DATE DEFAULT '1999-12-31'; 

DECLARE l_datetime DATETIME DEFAULT '1999-12-31 23:59:59';

DECLARE l_varchar VARCHAR(255) DEFAULT 'This will not be padded';

SQL Server版文法

為了友善說明,資料庫使用SQL Server的示例資料庫,Northwind和pubs,如果SQL Server中沒有的話,可以按下面的方法安裝

1,下載下傳SQL2000SampleDb.msi,下載下傳位址是:

http://www.microsoft.com/downloads/details.aspx?FamilyId=06616212-0356-46A0-8DA2-EEBC53A68034&displaylang=en

2,安裝後,到預設目錄C:\SQL Server 2000 Sample Databases 有instnwnd.sql ,instpubs.sql兩個檔案

3,在sql server中運作這兩個sql 就可以建立你Northwind和pubs資料庫。

下面開始學T-SQL的文法

一.注釋

-- 單行注釋,從這到本行結束為注釋,類似C++,c#中//

/* … */ 多行注釋,類似C++,C#中/* … */

二.變量(int, smallint, tinyint, decimal,float,real, money ,smallmoney, text ,image, char, varchar。。。。。。)

文法:

DECLARE

{

{@local_variable data_type}

} [,...n]

例如:

declare @ID int --申明一個名為@ID的變量,類型為int型

三.在SQL Server視窗中列印出變量的值

PRINT 'any ASCII text' | @local_variable | @@FUNCTION | string_expr

四.變量指派

--從資料表中取出第一行資料的ID,指派給變量@id,然後列印出來

Declare @ID int

Set @ID = (select top(1) categoryID from categories)

Print @ID

在SQL中,我們不能像代碼那樣直接給變量指派,例如@id = 1,如果要達到這樣的功能,可以這樣寫:

Set @ID = (select 1) -- 類似 @ID=1

Select @id=1 -- 類似 @ID=1

五.變量運算(+,-,*,/,……)

以下必要時候省略變量申明

Set @ID = (select 1+5) --類似 @ID=1+5

Set @ID=(select 1-@ID) --類似 @ID=1-@ID

六.比較操作符

? > (greater than).

? < (less than).

? = (equals).

? <= (less than or equal to).

? >= (greater than or equal to).

? != (not equal to).

? <> (not equal to).

? ! < (not less than).

? !> (not greater than).

沒什麼說的

七.語句塊:Begin … end

将多條語句作為一個塊,類似與C++,C#中的{ }

Begin

Set @ID1 = (select 1)

Set @ID2 = (select 2)

End

八.If, if…else…

IF Boolean_expression

{sql_statement | statement_block}

[ELSE

{sql_statement | statement_block}]

If @id is not null

Print ‘@id is not null

if @ID = 1

Set @ID = (select 1 + 1)

else

set @ID=(select 1+2)

上面的例子用到了比較操作符,語句塊,和IF的文法。

九.執行其他存儲過程 EXEC

例如

EXEC dbo.[Sales by Year] @Beginning_Date=’1/01/90’, @Ending_Date=’1/01/08’

十.事務

BEGIN TRAN[SACTION] [transaction_name | @tran_name_variable]

BEGIN TRAN

-- 做某些操作,例如Insert into …

if @@error <> 0

ROLLBACK TRAN

END

COMMIT TRAN

十一.遊标

我們可以在存儲過程中用Select語句取出每一行資料進行操作,這就需要用到遊标。

DECLARE cursor_name CURSOR

[LOCAL | GLOBAL]

[FORWARD_ONLY | SCROLL]

[STATIC | KEYSET | DYNAMIC | FAST_FORWARD]

[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]

[TYPE_WARNING]

FOR select_statement

[FOR UPDATE [OF column_name [,...n]]]

DECLARE @au_id varchar(11), @au_fname varchar(20) –申明變量

--申明一個遊标

DECLARE authors_cursor CURSOR FOR

SELECT au_id, au_fname FROM authors

--打開遊标

OPEN authors_cursor

--取出值

FETCH NEXT FROM authors_cursor INTO @au_id, @au_fname

--循環取出遊标的值

WHILE @@FETCH_STATUS = 0

Print @au_id

Print @au_fname

Print ‘ ’

FETCH NEXT FROM authors_cursor

INTO @au_id, @au_fname

CLOSE authors_cursor –關閉遊标

DEALLOCATE authors_cursor --釋放遊标

我覺得上面的是存儲過程常用的一些東東,如果要更深入的了解,更詳細的幫助,請參考SQL Server的幫助文檔

例子:

我自己做了一個,沒有問題,你可以看一下   

  use   Northwind   

  go   

  create   proc   test   

      @StartOrderID   int,   

      @EndOrderID   int,   

      @Code   varchar(1000)   Out   

  As   

      Begin   

          Declare   @tmp   int   

                  Set   @Code=''           

                  Declare   #cur_orders   cursor     for     Select   OrderID   From   Orders     

                          where   OrderID>=@startOrderID   and   OrderID<=@EndOrderID   

                          for   read   only   

                  Open   #cur_Orders   

                  fetch   next   from   #cur_orders   into   @tmp   

                    while   @@fetch_Status=0   

                      Begin   

                              Set   @Code=@Code+'-'+convert(varchar(8),@tmp)   

                                fetch   next   from   #cur_orders   into   @tmp   

                      End   

                  close   #cur_Orders   

                  Deallocate   #cur_Orders   

                  return   

      End   

  go   

續2   

        String   ret=null;   

          try{   

              Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");   

              String   url   

  ="jdbc:microsoft:sqlserver://192.168.0.102:1433;DatabaseName=Northwind";   

              String   user="sa";   

              String   password="";   

              Connection   conn=   DriverManager.getConnection(url,user,password);   

              CallableStatement   stmt=conn.prepareCall("exec   test   ?,?,?");   

              stmt.setInt(1,10248);   

              stmt.setInt(2,10284);   

              stmt.registerOutParameter(3,Types.VARCHAR);   

              stmt.setString(3,ret);   

              stmt.execute();   

              System.out.println(stmt.getString(3));   

              stmt.close();   

              stmt=null;   

              conn.close();   

          }catch(ClassNotFoundException   e){   

              e.printStackTrace();   

          }catch(SQLException   e){   

          }   

上面的例子沒有問題,針對你的情況,我又寫了一個,應該可以解決你現在的問題   

  --   建立一個表   

      Create   table   tmpOrders   (   

            OrderID   int,   

            CustomerID   nchar(5)   

    )   

  --把Orders   裡的OrderID列全部插入,這樣Orders與tmpOrders之間就是1:1關系了   

  insert   into   tmpOrders   

  Select   distinct   orderID,'tmp'   from   Orders   

          Declare   @newOrderID   int   

          Declare   @newCustomerID   nchar(5)   

          Declare   @DummyInt   int   

          Declare   @DummyChar   nchar(5)   

                  Set   @Code=''       

                  /*   

                                                                                                                                  1:1     

                          temp   table/formal   table   is   synchronized   tmpOrders     <--->   Orders   

                          fetch   from   Orders,   update   tmpOrders   

                  */   

                  --   for   temp   table   

                  Declare   #cur_tmpOrders     Cursor   for   select   OrderID,CustomerID     

                                From   tmpOrders     

                                      where   OrderID>=@startOrderID     

                                      and   OrderID<=@EndOrderID                                     

                                      for     update   

                  --for   formal   table   

                  Declare   #cur_orders   cursor     for     Select   OrderID,CustomerID     

                            From   Orders     

                          where   OrderID>=@startOrderID     

                          and   OrderID<=@EndOrderID     

                  Open   #cur_tmpOrders   

                  fetch   next   from   #cur_tmpOrders   into   @DummyInt,@dummyChar   --Important!!!   

                  fetch   next   from   #cur_orders   into   @NewOrderID,@NewCustomerID   

                              --Set   @Code=@Code+'-'+convert(varchar(8),@NewOrderID)   

                              --update   tempOrders   use   corresponding   Orders'   data   

                                Update   tmpOrders   set   customerID=@newCustomerID     

                                          where   current   of   #cur_tmpOrders     

                                --pay   attention   to   sequence   of   cursor   fetch   action!   

                                fetch   next   from   #cur_tmpOrders   into   @DummyInt,@dummyChar   

                                if   @@fetch_Status<>0     break;   --   沒有行了   

                                fetch   next   from   #cur_orders   into   @newOrderID,@NewCustomerID   

                  close   #cur_tmpOrders   

                  Deallocate   #cur_tmpOrders   

                  Set   @Code='Ok'   

      End  

程式如下   

              String   url=   

  "jdbc:microsoft:sqlserver://192.168.0.102:1433;DatabaseName=Northwind";   

              CallableStatement   stmt=conn.prepareCall("exec   test     ?,?,?");   

              stmt.registerOutParameter(3,Types.VARCHAR,1000);   

              stmt.executeUpdate();   

              conn=null;   

 ORACLE的基本文法集錦:

/Files/kkcheng/ORACLE的基本文法集錦.doc