Ⅰ mysql中,訪問量可以用觸發器或存儲過程么select某些數據一次相當於訪問量加1
select是不能用觸發器的。只有UPDATE或DELETE操作才能定義觸發器。
如果真的在select上定義了觸發器有什麼後果?不單單是你訪問頁面時會查詢數據,在你修改數據的時候同樣也要查詢數據。這時怎麼區分到底是訪問了還是沒有訪問呢?
存儲過程是預先定義好的mysql「函數」。函數不調用就無法生效,因此不能實現你的需求。
關系資料庫的觸發器和存儲過程是一個非常可選的功能,在大部分情況下,是不需要用到的。觸發器的目的是在你修改資料庫內容時,自動幫助你完成一些工作,保證數據的完整性。存儲過程實質上是把你的一部分操作資料庫的代碼邏輯存儲起來以備調用。其實這些特性都可以用普通的SQL和事務來實現,而且更靈活,更利於設計。因此在使用觸發器或存儲過程之前要慎重。
Ⅱ mysql存儲過程為什麼不推薦使用
維護不方便,對資料庫壓力不較大,不易於資料庫集群的擴展和遷移。
能夠在業務系統層面做的邏輯盡量不要用存儲過程來做。
以後做資料庫的遷移的時候,換了資料庫,存儲過程可能要重寫或重構。但是如果放在業務代碼層去實現對應的邏輯,資料庫換了之後,更改對應的連接驅動,業務代碼不用做任何吸怪。
Ⅲ mysql 存儲過程怎麼進行性能優化
在資料庫的開發過程中,經常會遇到復雜的業務邏輯和對資料庫的操作,這個時候就會用存儲過程來封裝資料庫操作。如果項目的存儲過程較多,書寫又沒有一定的規范,將會影響以後的系統維護困難和大存儲過程邏輯的難以理解,另外如果資料庫的數據量大或者項目對存儲過程的性能要求很,就會遇到優化的問題,否則速度有可能很慢,經過親身經驗,一個經過優化過的存儲過程要比一個性能差的存儲過程的效率甚至高幾百倍。下面介紹某一個MySQL存儲過程優化的整個過程。
在本文中,需要被優化的存儲過程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
insert into tb_testnum select boxnumber,usertype from tb_testnum_tmp where boxnumber= p_boxnumber;
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnumok';
在存儲過程中使用到的表tb_testnum結構如下:
drop table if exists tb_testnum;
create table tb_testnum
(
boxnumber varchar(30) not null,
usertype int not null
);
create unique index idx1_tb_testnum ontb_testnum(boxnumber);
在存儲過程中使用到的另外一張表tb_testnum_tmp結構如下:
drop table if exists tb_testnum_tmp;
create table tb_testnum_tmp
(
boxnumber varchar(30) not null,
usertype int not null
);
create unique index idx1_tb_testnum_tmp ontb_testnum_tmp(boxnumber);
從兩個表的結構可以看出,tb_testnum和tb_testnum_tmp所包含的欄位完全相同,存儲過程pr_dealtestnum的作用是根據輸入參數將tb_testnum_tmp表的數據插入到tb_testnum表中。
很明顯,雖然能夠實現預期的功能,但存儲過程pr_dealtestnum的代碼還有改進的地方。
下面,我們一步一步來對其進行優化。
優化一
存儲過程pr_dealtestnum的主體是一條insert語句,但這條insert語句裡面又包含了select語句,這樣的編寫是不規范的。因此,我們要把這條insert語句拆分成兩條語句,即先把數據從tb_testnum_tmp表中查找出來,再插入到tb_testnum表中。修改之後的存儲過程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
declare p_usertype int;
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
insert into tb_testnum values(p_boxnumber,p_usertype);
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
優化二
在向tb_testnum表插入數據之前,要判斷該條數據在表中是否已經存在了,如果存在,則不再插入數據。同理,在從tb_testnum_tmp表中查詢數據之前,要先判斷該條數據在表中是否存在,如果存在,才能從表中查找數據。修改之後的存儲過程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype fromtb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum values(p_boxnumber,p_usertype);
leave pr_dealtestnum_label;
end;
else
begin
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
優化三
不管向tb_testnum表插入數據的操作執行成功與否,都應該有一個標識值來表示執行的結果,這樣也方便開發人員對程序流程的追蹤和調試。也就是說,在每條leave語句之前,都應該有一個返回值,我們為此定義一個輸出參數。修改之後的存儲過程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum values(p_boxnumber,p_usertype);
set p_result = 0;
leave pr_dealtestnum_label;
end;
else
begin
set p_result = 2;
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
優化四
我們注意到「insert into tb_testnum values(p_boxnumber,p_usertype);」語句中,tb_testnum表之後沒有列出具體的欄位名,這個也是不規范的。如果在以後的軟體版本中,tb_testnum表中新增了欄位,那麼這條insert語句極有可能會報錯。因此,規范的寫法是無論tb_testnum表中有多少欄位,在執行insert操作時,都要列出具體的欄位名。修改之後的存儲過程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype);
set p_result = 0;
leave pr_dealtestnum_label;
end;
else
begin
set p_result = 2;
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
優化五
在執行insert語句之後,要用MySQL中自帶的@error_count參數來判斷插入數據是否成功,方便開發人員跟蹤執行結果。如果該參數的值不為0,表示插入失敗,那麼我們就用一個返回參數值來表示操作失敗。修改之後的存儲過程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount> 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0then
begin
insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype);
if @error_count<>0 then
begin
set p_result= 3;
end;
else
begin
set p_result= 0;
end;
end if;
end;
else
begin
set p_result = 2;
end;
end if;
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
Ⅳ 在MYSQL中使用存儲過程要設置什麼地方嗎解決辦法
幾個去 IBM 面試的兄弟回來抱怨:去了好幾個不同的 IBM
項目組,幾乎每個面試官問到資料庫的時候都要問用沒用過存儲過程,煩人不?大家去面的程序員,又不是
筆者認為,存儲過程說白了就是一堆 SQL 的合並。中間加了點邏輯控制。
但是存儲過程處理比較復雜的業務時比較實用。
比如說,一個復雜的數據操作。如果你在前台處理的話。可能會涉及到多次資料庫連接。但如果你用存儲過程的話。就只有一次。從響應時間上來說有優勢。
也就是說存儲過程可以給我們帶來運行效率提高的好處。
另外,程序容易出現 BUG
數據量小的,或者和錢沒關系的項目不用存儲過程也可以正常運作。mysql 的存儲過程還有待實際測試。如果是正式項目,建議你用 sql
server 或 oracle
的存儲過程。數據與數據之間打交道的話,過程會比程序來的快的多。面試官問有沒有用存儲,實際上就是想知道前來面試的程序員到底做過數據量大的項目沒。如
果是培訓出來的,或者小項目小公司出來的,對存儲肯定接觸的少了。
所以,要想進大公司,沒有豐富存儲過程經驗,是不行的。
錯。存儲過程不僅僅適用於大型項目,對於中小型項目,使用存儲過程也是非常有必要的。其威力和優勢主要體現在:
1.存儲過程只在創造時進行編譯,以後每次執行存儲過程都不需再重新編譯,而一般 SQL
語句每執行一次就編譯一次,所以使用存儲過程可提高資料庫執行速度。
2.當對資料庫進行復雜操作時(如對多個表進行
Update,Insert,Query,Delete
時),可將此復雜操作用存儲過程封裝起來與資料庫提供的事務處理結合一起使用。這些操作,如果用程序來完成,就變成了一條條的 SQL
語句,可能要多次連接資料庫。而換成存儲,只需要連接一次資料庫就可以了。
3.存儲過程可以重復使用,可減少資料庫開發人員的工作量。
4.安全性高,可設定只有某此用戶才具有對指定存儲過程的使用權。存儲過程的缺點
1:調試麻煩,但是用 PL/SQL Developer 調試很方便!彌補這個缺點。
2:移植問題,資料庫端代碼當然是與資料庫相關的。但是如果是做工程型項目,基本不存在移植問題。
3:重新編譯問題,因為後端代碼是運行前編譯的,如果帶有引用關系的對象發生改變時,受影響的存儲過程、包將需要重新編譯(不過也可以設置成運行時刻自動編譯)。
4:如果在一個程序系統中大量的使用存儲過程,到程序交付使用的時候隨著用戶需求的增加會導致數據結構的變化,接著就是系統的相關問題了,最後如果用戶想維護該系統可以說是很難很難、而且代價是空前的。維護起來更加麻煩
Ⅳ mysql 的存儲過程可以封裝資料庫操作嗎
存儲過程不存在操作或是不操作觸發器的問題,要先理解觸發器的含義。
觸發器分兩類,一類是基於表數據的觸發,一類是基於資料庫對象的觸發。
實際應用中第一類比較常用,它是在對表數據進行 插入 修改 刪除 的操作時觸發,執行觸發器中的腳本,換言之,就是如果你的存儲過程有涉及到對該表的 插入 修改 刪除 數據操作,而且該表也存在這些操作對應的觸發器,那麼肯定會觸發也就是執行這個觸發器,反之,不會執行。
Ⅵ mysql存儲過程的基本用法有哪些
mysql存儲過程的基本用法有哪些
在外部程序訪問資料庫時(例如 PHP),要組織很多 SQL 語句。
特別是業務邏輯復雜的時候,一大堆的 SQL 和條件夾雜在 PHP 代碼中,讓人不寒而慄。現在有了 MySQL 存儲過程,業務邏輯可以封裝存儲過程中,這樣不僅容易維護,而且執行效率也高。
一、MySQL 創建存儲過程
"pr_add" 是個簡單的 MySQL 存儲過程,這個MySQL 存儲過程有兩個 int 類型的輸入參數 "a"、"b",返回這兩個參數的和。
復制代碼 代碼如下:
drop procere if exists pr_add;
計算兩個數之和
復制代碼 代碼如下:
create procere pr_add
(
a int,
b int
)
begin
declare c int;
if a is null then
set a = 0;
end if;
if b is null then
set b = 0;
end if;
set c = a + b;
select c as sum;
/*
return c;
不能在 MySQL 存儲過程中使用。return 只能出現在函數中。
*/
end;
二、調用 MySQL 存儲過程
復制代碼 代碼如下:
call pr_add(10, 20);
執行 MySQL 存儲過程,存儲過程參數為 MySQL 用戶變數。
復制代碼 代碼如下:
set @a = 10;
set @b = 20;
call pr_add(@a, @b);
三、MySQL 存儲過程特點
創建 MySQL 存儲過程的簡單語法為:
復制代碼 代碼如下:
create procere 存儲過程名字()
(
[in|out|inout] 參數 datatype
)
begin
MySQL 語句;
end;
MySQL 存儲過程參數如果不顯式指定"in"、"out"、"inout",則默認為"in"。習慣上,對於是"in" 的參數,我們都不會顯式指定。
1. MySQL 存儲過程名字後面的"()"是必須的,即使沒有一個參數,也需要"()"
2. MySQL 存儲過程參數,不能在參數名稱前加"@",如:"@a int"。下面的創建存儲過程語法在 MySQL 中是錯誤的(在 SQL Server 中是正確的)。 MySQL 存儲過程中的變數,不需要在變數名字前加"@",雖然 MySQL 客戶端用戶變數要加個"@"。
復制代碼 代碼如下:
create procere pr_add
(
@a int, -- 錯誤
b int -- 正確
)
3. MySQL 存儲過程的參數不能指定默認值。
4. MySQL 存儲過程不需要在 procere body 前面加 "as"。而 SQL Server 存儲過程必須加 "as" 關鍵字。
復制代碼 代碼如下:
create procere pr_add
(
a int,
b int
)
as -- 錯誤,MySQL 不需要 "as"
begin
mysql statement ...;
end;
5. 如果 MySQL 存儲過程中包含多條 MySQL 語句,則需要 begin end 關鍵字。
復制代碼 代碼如下:
create procere pr_add
(
a int,
b int
)
begin
mysql statement 1 ...;
mysql statement 2 ...;
end;
6. MySQL 存儲過程中的每條語句的末尾,都要加上分號 ";"
復制代碼 代碼如下:
...
declare c int;
if a is null then
set a = 0;
end if;
...
end;
7. MySQL 存儲過程中的注釋。
復制代碼 代碼如下:
/*
這是個
多行 MySQL 注釋。
*/
declare c int; -- 這是單行 MySQL 注釋 (注意 -- 後至少要有一個空格)
if a is null then # 這也是個單行 MySQL 注釋
set a = 0;
end if;
Ⅶ mysql 存儲過程 執行報錯 我創建了一個簡單的存儲過程,成功了,但是在call執行調用的時候怎麼老是報錯呢
create procere proprice() is
begin
select avg(price) as average from procts;
end;
以上就是規范的格式,請不要添加額外的東西,執行之後調用即可。
如果有其他問題,你可以先網路一下存儲過程的規范應用
Ⅷ mysql存儲過程 和 觸發器的優缺點 問題
缺點是觸發器的缺點,
而有點是存儲過程的優點,
所以推薦使用存儲過程。