mysql存儲過程事務回滾
CREATE PROCEDURE `xxxx`( )
BEGIN
#設置事務
DECLARE t_error INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;
#開啟事務
START TRANSACTION;
#插入數據
INSERT INTO 表2(欄位21,欄位22,欄位23)
SELECT 欄位11,欄位12,欄位13 FROM 表1 where xxxx ;
#刪除數據
delete 表1 where xxx;
#以上兩步操作出現任何失誤都將回滾
IF t_error = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
end;
『貳』 MySQL存儲過程事務回滾中有游標遍歷,如何處理
請說詳細些,最好有貼代碼出來
『叄』 mysql存儲過程中有沒有類似try catch
在存儲過程中使用事務時,如果沒有try…catch語句,那麼當set xact_abort
on時,如果有錯誤發生,在批處理語句結束後,系統會自動回滾所有的sql操作。當set xact_abort
off時,如果有錯誤發生,在批處理語句結束後,系統會執行所有沒有發生錯誤的語句,發生錯誤的語句將不會被執行。
在存儲過程中使用事務時,如果存在try…catch語句塊,那麼當捕獲到錯誤時,需要在catch語句塊中手動進行Rollback操作,否則系統會給客戶端傳遞一條錯誤信息。如果在存儲過程開始處將set
xact_abort
on,那麼當有錯誤發生時,系統會將當前事務置為不可提交狀態,即會將xact_state()置為-1,此時只可以對事務進行Rollback操作,不可進行提交(commit)操作,那麼我們在catch語句塊中就可以根據xact_state()的值來判斷是否有事務處於不可提交狀態,如果有則可以進行rollback操作了。如果在存儲過程開始處將set
xact_abort
off,那麼當有錯誤發生時,系統不會講xact_state()置為-1,那麼我們在catch塊中就不可以根據該函數值來判斷是否需要進行
rollback了,但是我們可以根據@@Trancount全局變數來判斷,如果在catch塊中判斷出@@Trancount數值大於0,代表還有未提交的事務,既然進入catch語句塊了,那麼還存在未提交的事務,該事務應該是需要rollback的,但是這種方法在某些情況下可能判斷的不準確。推薦的方法還是將set
xact_abort on,然後在catch中判斷xact_state()的值來判斷是否需要Rollback操作。
下面我們來看看兩個例子:
一.使用Set xact_abort on
代碼
Create proc myProcere
As
begin
set xact_abort on;
begin try
begin tran
insert into TestStu values('Terry','boy',23);
insert into TestStu values('Mary','girl',21);
commit tran
end try
begin catch
--在此可以使用xact_state()來判斷是否有不可提交的事務,不可提交的事務
--表示在事務內部發生錯誤了。Xact_state()有三種值:-1.事務不可提交;
--1.事務可提交;0.表示沒有事務,此時commit或者rollback會報錯。
if xact_state()=-1
rollback tran;
end catch
end
二.使用Set xact_abort off
代碼
Create proc myProcere
As
begin
set xact_abort off;
begin try
begin tran
insert into TestStu values('Terry','boy',23);
insert into TestStu values('Mary','girl',21);
commit tran
end try
begin catch
--在此不可以使用xact_state來判斷是否有不可提交的事務
--只可以使用@@Trancount來判斷是否有還未提交的事務,未提交的事務未必
--就是不可提交的事務,所以使用@@TranCount>0後就RollBack是不準確的
if @@TranCount>0
rollback tran;
end catch
end
另外,對於@@Trancount需要說明的是,begin tran 語句將 @@Trancount加 1。Rollback tran將
@@Trancount遞減到 0,但 Rollback tran savepoint_name 除外,它不影響 @@Trancount。Commit tran 或 Commit work 將 @@Trancount 遞減 1。
『肆』 mysql存儲過程執行一半出現異常會怎麼辦
如果在存儲過程調用的時候顯式的調用了事務處理,那麼,會回滾,否則執行到那裡就在哪裡生效。
『伍』 mysql基本語句詳細教程
看他們網上的,寫得都是千篇一律,同時,好多也寫得不是很好,下面是我自己總結的有關mysql的使用細節,也是我在學習過程中的一些記錄吧,希望對你有點幫助,後面有關存儲過程等相關操作還沒有總結好,下次總結好了再發給你吧,呵呵~~~~~
MySql學習筆記
MySql概述:MySql是一個種關聯資料庫管理系統,所謂關聯資料庫就是將數據保存在不同的表中,而不是將所有數據放在一個大的倉庫中。這樣就增加了速度與提高了靈活性。並且MySql軟體是一個開放源碼軟體。
注意,MySql所支持的TimeStamp的最大范圍的問題,在32位機器上,支持的取值范圍是年份最好不要超過2030年,然後如果在64位的機器上,年份可以達到2106年,而對於date、與datetime這兩種類型,則沒有關系,都可以表示到9999-12-31,所以這一點得注意下;還有,在安裝MySql的時候,我們一般都選擇Typical(典型安裝)就可以了,當然,如果還有其它用途的話,那最好選擇Complete(完全安裝);在安裝過程中,一般的還會讓你進行伺服器類型的選擇,分別有三種伺服器類型的選擇,(Developer(開發機)、Server Machine(伺服器)、Dedicated MySql Server Machine(專用MYSQL伺服器)),選擇哪種類型的伺服器,只會對配置向導對內存等有影響,不然其它方面是沒有什麼影響的;所以,我們如果是開發者,選擇開發機就可以啦;然後接下來,還會有資料庫使用情況對話框的選擇,我們只要按照默認就可以啦;
連接與斷開伺服器:
連接:在windows命令提示符下輸入類似如下命令集:mysql –h host –u user –p
例如,我在用的時候輸入的是:mysql –h localhost –u root –p
然後會提示要你輸入用戶密碼,這個時候,如果你有密碼的話,就輸入密碼敲回車,如果沒有密碼,直接敲回車,就可以進入到資料庫客戶端;連接遠程主機上的mysql,可以用下面的命令:mysql –h 159.0.45.1 –u root –p 123
斷開伺服器:在進入客戶端後,你可以直接輸入quit然後回車就可以了;
下面就資料庫相關命令進行相關說明
你可以輸入以下命令對資料庫表格或者資料庫進行相關操作,在這里就省略了,然後直接進行文字說明了;
Select version(),current_date;//從伺服器得到當前mysql的版本號與當前日期
Select user(); //得到當前資料庫的所有用戶
Use databasename; 進入到指定的資料庫當中,然後就可以操作這個資料庫當中的表格了
Show databases; //查詢目前資料庫中所有的資料庫,並且顯示出來;
Create batabase databasename;創建資料庫,例如:create database manager;
Show tables; //查看當前資料庫中的所有表格;
Create table tablename(colums);創建表,並且給表指定相關列,例如:create table pet(name varchar(20),owner varchar(20),species varchar(20),sex char(1),birth date,death date);
Describe tablename;將表當中的所有信息詳細顯示出來,例如:describe pet;
可以用命令一次插入多條記錄,例如:
Insert into pet values(『Puffball』,』Diane』,』hamster』,』f』,』1993-12-3』,null),( 『Puffball』,』Diane』,』hamster』,』f』,』1993-12-3』,now());
Select * from pet; 從pet表當中查詢出所有的記錄,顯示出來;
Delete from pet where id=1;刪除ID為1的那一條記錄;
Update pet set birth=』2001-1-3』 where name=』Bowser』;更新name為Bowser的記錄當中的birth欄位的值;
Select distinct owner from pet;從pet表中選擇出owner欄位的值唯一的行,如果有多行記錄這個欄位的值相同,則只顯示最後一次出現這一值的一行記錄;
有關日期計算:
Select name,birth,curdate(),(year(curdate())-year(birth)) as age from pet;
此處,year()函數用於提取對應欄位的年份,當然類似的還有month(),day()等;
在mysql當中,sql語句可以使用like查詢,可以用」_」配任何單個字元,用」%」配任意數目字元,並且SQL模式默認是忽略大小寫,例如:select * from pet where name like 『%fy』;
當然也可以用正則表達式模式進行配。
同時在sql當中,也要注意分組函數、排序函數、統計函數等相關用法,在這里只列舉一二;
Select species,count(*) from pet group by speceis;
Select * from pet order by birth desc;
查詢最大值的相關操作:
Select max(age) from pet;
取前多少項記錄,這個主要用於分頁查詢操作當中,
Select * from pet order by birth desc limit 3;取前三條記錄,
Select * from pet order by birth desc limit 0,3;這個可以用於分頁查詢,limit後面的第一個參數,是起始位置,第二個參數是取記錄條數;
有關創建表格自增長欄位的寫法:
Create table person(id int(4) not null auto_increment,name char(20) not null,primary key (id));
修改表操作:
向表中增加欄位:注意,在這個地方,如果是增加多個欄位的時候,就要用括弧括起來,不然會有問題,如果是單個欄位的話,不用括弧也沒事;
Alter table test add(address varchar(50) not null default 『xm』,email varchar(20) not null);
將表中某個欄位的名字修改或者修改其對應的相關屬性的時候,要用change對其進行操作;
Alter table test change email email varchar(20) not null default 『zz』;//不修改欄位名
Alter table test change email Email varchar(30) not null;//修改欄位名稱
刪除表中欄位:
Alter table test drop email;//刪除單個欄位
Alter table test drop address,drop email;//刪除多列
可以用Drop來取消主鍵與外鍵等,例如:
Alter table test drop foreign key fk_symbol;
刪除索引:
Drop index index_name on table_name;
例如:drop index t on test;
向表中插入記錄:注意,當插入表中的記錄並不是所有的欄位的時候,應該要在前面列出欄位名稱才行,不然會報錯;
Insert into test(name) values(『ltx』);
Insert into test values(1,』ltx』);
也可以向表中同時插入多列值,如:
Insert into test(name) values(『ltx』),(『hhy』),(『xf』);
刪除表中記錄:
Delete from test;//刪除表中所有記錄;
Delete from test where id=1;//刪除表中特定條件下的記錄;
當要從一個表或者多個表當中查詢出一些欄位然後把這些欄位又要插入到另一個表當中的時候,可以用insert …..select語法;
Insert into testt(name) (select name from test where id=4);
從文件中讀取行插入數據表中,可以用Load data infile語句;
Load data infile 『test.txt』 into table test;
可以用Describe語法進行獲取有關列的信息;
Describe test;//可以查看test表的所有信息,包括對應列欄位的數據類型等;
MySql事務處理相關語法;
開始一項新的事務:start transaction或者begin transaction
提交事務:commit
事務回滾:rollback
set autocommit true|false 語句可以禁用或啟用默認的autocommit模式,只可用於當前連接;
例子:
Start transaction;
Update person set name=』LJB』 where id=1;
Commit | rollback;
資料庫管理語句
修改用戶密碼:以root用戶為例,則可以寫成下面的;mysql –u root –p 舊密碼 –password 新密碼
Mysql –u root –password 123;//將root用戶的密碼修改成123,由於root用戶開始的時候,是沒有密碼的,所以-p舊密碼就省略了;
例如修改一個有密碼的用戶密碼:mysql –u ltx –p 123 –password 456;
增加一個用戶test1,密碼為abc,讓他可以在任何時候主機上登陸,並對所有資料庫有查詢、插入、修改、刪除的許可權。
Grant select,insert,update,delete on *.* to test1@」%」 identified by 『abc』;
增加一個test2用戶,密碼為abc,讓他只可以在localhost上登陸,並且可以對資料庫進行查詢、插入、修改、刪除操作;
Grant select,insert,update,delete on mydb.* to test2@localhost identified by 『abc』;
如果不想讓用戶test2有密碼,可以再輸入以下命令消掉密碼:
Grant select,insert,update,delete on mydb.* to test2@localhost identified by 「」;
備份資料庫常用命令:mysqlmp –h host –u username –p dbname>保存路徑與文件名
然後回車後,會讓你輸入用戶密碼,輸入密碼後,再回車就OK啦;
Mysqlmp –hlocalhost –uroot –p test >E:\db\test.sql
這一命令具體解釋下:
這個命令就是備份test資料庫,並且將備份的內容存儲為test.sql文件,並且保存在E:\db下面;
命令當中-p 前面的test是資料庫名,然後在資料庫名後面要跟上一個」>」,然後接下來,就是寫要保存的位置與保存文件的文件名;
將備份好的資料庫導入到資料庫當中去:也就是運行.sql文件將資料庫導入資料庫當中去->
首先你得創建資料庫,然後運行如下命令:mysql –hlocalhost –uroot –p linux<E:\db\test.sql然後回車,再輸入密碼就可以啦;
解釋下上面的命令:linux是就要導入的資料庫名字,然後後面要緊跟著「<」符號,然後後面就是要導入的資料庫文件;
將資料庫導出保存成XML文件、從XML文件導入數據到資料庫:
導出表中數據:mysql –X –h hostName –u userName –p Pwd –e 「use DatabaseName;sql;」 >xml文件名
或者用另外一種方式也行:mysqlmp –xml –h hostName –u userName –p pwd dbName tableName //這一種只用於顯示在當前的mysql客戶端,不保存到文件當中;
相關說明:-X代表的是文件的格式是XML,然後-e一寫不能掉,還有就是要用雙引號將要操作的語句括起來;單引號不行;
例如:mysql –X –hlocalhost –uroot –p –e 「use test;select * from pet;」>E:\db\out.xml
從XML文件導入數據到資料庫:
Insert into tableName values(1,load_file(『filepath』));
例如:insert into pet values(1,load_file(「E:\db\out.xml」));
查看資料庫狀態與查詢進程:
Show status;//查看狀態
Show processlist;//查看進程
更改用戶名,用以下命令:
Update set user=」新名字」 where user=」舊用戶名」;
給資料庫用戶設置管理員許可權:
Mysqladmin –h host –u username –p pwd;
以root用戶為例;
Mysqladmin –h localhost –u root –p 123;
存儲過程與函數
存儲程序和函數分別是用create procere和create function語句,一個程序要麼是一個程序要麼是一個函數,使用call語句來調用程序,並且程序只能用輸出變數傳回值;
要想在MySql5.1中創建子程序,必須具有create routine許可權,並且alter routine和execute許可權被自動授予它的創建者;
創建存儲過程:
首先聲明分隔符,所謂分隔符是指你通知mysql客戶端你已經輸入一個sql語句的字元或字元串符號,在這里我們就以「//」為分隔符;
Delimiter 分隔符\
如:delimiter //
再創建存儲過程:
Create procere 存儲過程名 ( )
聲明存儲過程開始:
begin
然後開始寫存儲過程體:
Select * from pet;
結束存儲過程:
End;//
剛剛的例子全部寫出來,完整的代碼就是:
Delimiter //
Create procere spt () //注意,這個地方,存儲過程名與括弧之間要有個空格
Begin
Select * from pet;
End;//到這里,整個存儲過程就算寫完啦
執行存儲過程:
Call 存儲過程名 ();//
如,我們執行剛剛創建的存儲過程,就是:
Call spt ();//
需要說明的是存儲過程名後面一定要加個空格,而後面那個括弧,則是用於傳送參數的參數列表;另外,我們創建存儲過程完成後,也只是創建了,但是只有調用call 存儲過程名 ();//後才算執行完畢,才能看到存儲過程的結果;
『陸』 mysql 存儲過程怎麼設置事務
CREATE DEFINER=`root`@`localhost` PROCEDURE `createBusiness`(parameter1 int)
BEGIN
#Routine body goes here...
DECLARE flag int DEFAULT parameter1;#聲明變數flag,將參數值賦給該變數
DECLARE uuidStr VARCHAR(32);#聲明一個長度為32位的字元串
DECLARE currentTime TIMESTAMP;#聲明一個類型為時間戳的變數
declare err INT default 0;#聲明一個整形變數err,默認值是0
declare continue handler for sqlexception set err=1;#當sqlexception handler捕捉到異常時,設置err=1
START TRANSACTION;#開始事務
WHILE flag>0 DO #注意: while不能空實現(在while塊中,裡面必須有語句)
#uuid()函數得到的字元串是'6ccd780c-baba-1026-9564-0040f4311e29',剔除裡面的-,得到一個32位的字元串
SET uuidStr = REPLACE(UUID(),'-','') ;
#得到當前的時間
SET currentTime = CURRENT_TIMESTAMP();
#執行插入語句,注意連接字元串的函數concat(str1,str2,...);其中str..也可以是數字類型
INSERT INTO
表名稱
(id,title,keyword,hasImage,isTodayHead,isShowInHome,isBigness,publishTime,originId,modify_time,isAnalysis)
VALUE
(uuidStr,CONCAT('事件標題',flag),CONCAT('關鍵字',flag),1,1,0,0,currentTime,CONCAT('xxxxxxx',flag),currentTime,1);
#每循環一次,flag要減去1,注意沒有flag--的語法
set flag = flag-1;
#在這里測試當err=1時,事務是否有了回滾,測試ok
#IF flag=7 THEN #注意在procere中給變數賦值要用到set,或在變數聲明時用default來父子,所以=號可以用來比較兩邊的值是否相等,<=>也可,區別先不去糾結。
#set err=1;
#END if;
END WHILE;
IF (err=0) THEN
commit;
select 'OK';
ELSE
rollback;
select 'err';
END IF;
END;
『柒』 mysql 存儲過程 DDL 參數
MySQL8.0 開始支持原⼦ DDL(atomic DDL),數據字典的更新,存儲引擎操作,寫⼆進制日誌結合成了一個事務。在沒有原⼦DDL之前,DROP TABLE test1,test2;如遇到server crash,可能會有test1被drop了,test2沒有被drop掉。下面來看下在MySQL8.0之前和MySQL8.0 數據字典的區別
在MySQL8.0 之前,Data Dictionary除了存在與.FRM, .TRG, .OPT ⽂件外,還存在於系統表中(MyISAM ⾮事務引擎表中),在MySQL8.0 ,Data Dictionary 全部存在於Data Dictionary Storage Engine(即 InnoDB表中),這使crash recovery 維持原⼦性成為了可能
存儲引擎⽀持
目前,只有InnoDB存儲引擎⽀持原子DDL,為了實現原子DDL,Innodb要寫DDL logs 到 mysql.innodb_ddl_log 表,這是⼀個隱藏在mysql.ibd 數據字典表空間⾥的數據字典表。要看mysql.innodb_ddl_log 中的內容,需要
SET GLOBALLOG_ERROR_VERBOSITY=3;(MySQL 8.0 默認為2,error log 記錄Errors and
warnings,不不記錄notes)
SET GLOBAL innodb_print_ddl_logs=1;
CREATE TABLEt1 (c1 INT)ENGINE=InnoDB;
查看error log
[Note] [MY-011066] InnoDB: DDL loginsert: [DDLrecord:DELETE SPACE,id=30,
thread_id=25, space_id=9, old_file_path=./test/t1.ibd]
[Note] [MY-011066]InnoDB:DDL logdelete:by id30
[Note] [MY-011066]InnoDB:DDL loginsert: [DDLrecord: REMOVECACHE,id=31,
thread_id=25, table_id=1066, new_file_path=test/t1]
[Note] [MY-011066]InnoDB:DDL logdelete:by id31
[Note] [MY-011066]InnoDB:DDL loginsert: [DDLrecord: FREE,id=32, thread_
id=25, space_id=9, index_id=143, page_no=4]
[Note] [MY-011066]InnoDB:DDL log delete:by id32
[Note] [MY-011066]InnoDB:DDL logpost ddl :begin for thread id: 25
[Note] [MY-011066]InnoDB:DDL logpost ddl :end for thread id: 25
原子DDL 操作步驟
准備:創建所需的對象並將DDL⽇志寫入 mysql.innodb_ddl_log表中。DDL日誌定義了如何前滾和回滾DDL操作。
執行:執⾏DDL操作。例如,為CREATE TABLE操作執⾏創建。
提交:更新數據字典並提交數據字典事務。
Post-DDL:重播並從mysql.innodb_ddl_log表格中刪除DDL⽇志。為確保回滾可以安全執⾏⽽不引⼊不⼀致性,在此最後階段執⾏⽂件操作(如重命名或刪除數據文件)。這一階段還從 mysql.innodb_dynamic_metadata的數據字典表刪除的動態元數據為了DROP TABLE,TRUNCATE和其它重建表的DDL操作。
⽆論事務是提交還是回滾,DDL日誌都會mysql.innodb_ddl_log在Post-DDL階段重播並從表中刪除 。mysql.innodb_ddl_log如果伺服器在DDL操作期間暫停,DDL⽇志應該只保留在表中。在這種情況下,DDL⽇志會在恢復後重播並刪除。
在恢復情況下,當伺服器重新啟動時,可能會提交或回退DDL事務。如果在重做⽇志和⼆進制日誌中存在DDL操作的提交階段期間執⾏的數據字典事務,則該操作被認為是成功的並且被前滾。否則,在InnoDB重放數據字典重做日誌時回滾不完整的數據字典事務 ,並且回滾DDL事務。
原⼦DDL ⽀持類型
• DROP TABLES , all tables dropped or none
• DROP SCHEMA, all entities in the schema are dropped, or none
• Note that atomic DDL statements will be rolled back or committed even in case of crash, e.g. RENAME TABLES
• CREATE TABLE would be successfully committed or rolled back (no orphan ibd left)
• TRUNCATE TABLE (including InnoDB tables with FTS AUX tables) would be successfully committed or rolled back
• RENAME TABLES, all or none
• ALTER TABLE successful or not done
示例
結論
在MySQL8.0之前,alter table 操作在server crash的情況下,會遺留.frm,.ibd文件。MySQL8.0 能實現原⼦DDL(包括 DROP TABLE, DROP SCHEMA, CREATE TABLE, TRUNCATE TABLE, ALTER TABLE),alter table 操作,在server crash的情況下,不會遺留.frm,.ibd臨時文件。讓我們⼀起期待MySQL8.0 GA的到來吧!
『捌』 thinkphp調用mysql存儲過程 ,求助,具體點好嗎,格式猜不出來…
thinkPHP的調用
$model = M("");
$data = $model -> query("CALL abcas(1,'[email protected]')");//調用存儲過程
mp($data);//輸出存儲過程的返回值
存儲過程部分
BEGIN -- 存儲過程開始
START TRANSACTION; -- 開始事務
#Routine body goes here...
SET @x = 1; -- 定義變數,通過這個變數判斷知道到的地方,事務成功@x返回大於0,否則返回0
update lzh_members set user_email = em where id = tid;
if row_count() > 0 then -- 判斷語句是否執行成功
update lzh_members set user_type = 0 where id = tid;
if row_count() > 0 then
update lzh_members set user_type = 2 where id = tid;
if row_count() > 0 then
SET @x = 5;
select @x;
commit; -- 事務提交
ELSE
SET @x = 0;
select @x;
rollback; -- 事務回滾
end if;
ELSE
SET @x = 0;
select @x;
rollback; -- 事務回滾
end if;
ELSE
SET @x = 0;
select @x;
rollback; -- 事務回滾
end IF;
END --存儲過程結束
『玖』 mysql 存儲過程中update影響行數為0,回滾
使用FOUND_ROWS() 獲得影響的行數,再用IF判斷是否等於0就行了。
--開始事務
starttransaction;
callsetCoin(zjAmount,0,`uid`,liqType,`type`,info,_betId,serializeId,'');
updateblast_betssetlotteryNo=_kjData,zjCount=_zjCount,bonus=zjAmount,fanDianAmount=_fanDianAmountSelfwhereid=_betId;
IFFOUND_ROWS()=0THEN
ROLLBACK;
ELSE
COMMIT;
ENDIF;
commit;