【997755.com澳门葡京】存款和储蓄进度的选取,Error使用简便小结

概述  

 最近因为业务的供给写了一段时间存款和储蓄进程,开掘后面写的贮存进程存在有的不胆战心惊的地方,特别是T奥迪Q5Y…CATCH中嵌套事务的写法;尽管事先写的并从未错,但是依然埋藏着极大的隐患在里边。希望那篇文章能给大家有些参照;小说内容有点长还望耐心阅读。

 

 

 使用中平时用到@@Error来判断上二个说话是或不是实施成功,对此小结一下,可能有个别不可相信,招待提议。

偶尔为了多少总体大家会启用到事情。经常的时候布帆无恙,假使rollback
呢?

事情定义:

一.插入测试数据

----创建表
DROP TABLE score
GO
CREATE TABLE [dbo].[score](
    id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
    name VARCHAR(50) NOT NULL,
    score INT NOT NULL CHECK (score>=0),
    months INT NOT NULL,
    createtime DATETIME NOT NULL DEFAULT GETDATE()
)

---根据姓名月份查询分数
CREATE INDEX IX_score_name ON score(name,months) include(score)
---根据月份查询最高分数
CREATE INDEX IX_score_months ON score(months) include(name,score)
---创建姓名和月份组合的唯一索引
CREATE UNIQUE INDEX IX_score_months_name ON score(months,name)

------插入测试数据
TRUNCATE TABLE score

INSERT INTO score(name,score,months) 
VALUES('li',50,10),('chen',70,10),('zhang',80,10),('wang',90,10),('li',50,11),('chen',70,11),('zhang',80,11),('wang',90,11)

SELECT * FROM score;

997755.com澳门葡京 1

1.1  介绍

SQL SEQashqaiVERubicon 中@@表示系统全局变量

(一)   重回实行的上3个 Transact-SQL
语句的错误号,即使进行未有不当,则赶回 0 。

997755.com澳门葡京 ,(二)   要是不当是 sys.messages 目录视图中的错误之壹,则 @@E宝马7系ROENCORE 将涵盖
sys.messages.message_id 列中代表该错误的值。  能够在 sys.messages
中查阅与 @@E奥迪Q5RO昂科拉 错误号相关的文件新闻。

(三)   由于 @@E宝马7系RO景逸SUV在每一条语句施行后被免去并且重新初始化,因而应在说话验证后旋即查看它,或将其保存到2个有个别变量中以备未来翻看。

 

最简便易行的3个回滚

政工是单个的干活单元。如若某壹专门的学业成功,则在该事务中开始展览的持有数据变动均会

2.THROW

THROW是在贰零1贰版本中引进的,在稍微场景个中,应用程序端不做一些合法性的辨证,那个验证会被放在数据库端来验证。当数码库端验证输入的消息不合规时索要主动抛出10分来刹车代码的实践。

THROW既能够收到错误新闻抛错提示,同时也可以手动抛出错误到CATCH中。语法如下:

;THROW

THROW [ { error_number | @local_variable }, 

        { message | @local_variable }, 

        { state | @local_variable } ]  

[ ; ]

参数

error_number
表示异常的常量或变量。 error_number是int并且必须为大于或等于 50000 且小于或等于 2147483647,如果CATCH中使用RAISERROR来接收错误信息那么指定的error_number必须在sys.messages 中存在;如果使用CATCH来接收则不需要。

消息
描述异常的字符串或变量。 消息是nvarchar(2048)。

状态
在 0 到 255 之间的常量或变量,指示与消息关联的状态。 状态是tinyint。

注意:

壹.THROW代码前务须求用分号,因为THROW会中断代码的执行,所以1旦将THROW放在CATCH中时务必放在ROLLBACK
TRAN之后,不然不会回滚事务导致对象向来处于提交状态被锁。

2.THROW放CATCH中能够直达RAISE中华VROMurano同样的遵守,同时还简便了代码。

  1. THROW能回到精确的错误代码行号,而RAISE奥德赛ROENCORE无法

参考:

1.二  圭臬及使用

(1)  分析施行SQL出现错误,后续脚本的执市价况

执行语句:

UPDATE tbOrder SET OrderNo = ‘201605010008’ WHERE OrderNo =
‘201605010001’

–试行上一步出现外键约束错误,并且继续实施下一步(5四七为束缚错误)

PENCOREINT @@E凯雷德ROXC60  –输出错误号

 

UPDATE tbOrder SET OrderAmount = ‘ABC’ WHERE OrderNo = ‘201605010001’

–在实践上一步时出现类型极度,并且不实行上边包车型地铁步调

PRINT @@ERROR  –未输出

 

说明:第3个SQL出错后,还是进行了前面包车型大巴代码,输出了@@Error错误号,第二个SQL出错后径直终止后续实践。

证实实施SQL出现谬误后,有的错误会间接终止后续施行,有的出现谬误后照旧能够继续推行后续脚本

 

(2)  询问成功后,系统变量@@Error变为0

 推行语句:

DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

PRINT ‘Delete: ‘ + CAST(@@ERROR AS VARCHAR(20))   –输出

SELECT 1  

PRINT ‘Select: ‘ + + CAST(@@ERROR AS VARCHAR(20))  –输出 Select:0 

 

说明:实施SQL 成功后,@@Error参数棉被服装置为0

 

(3)  通过Try Catch捕获错误,输出@@Error

a)  照旧地方的删除操作,发生外键约束难题

推行语句:

BEGIN TRY

    DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

    P奥迪Q7INT ‘DELETE ‘ + CAST(@@E卡宴RO奥迪Q五 AS VAMuranoCHA牧马人(20))   –未有出口

END TRY

BEGIN CATCH

    PRINT ‘CATCH ‘ + CAST(@@ERROR AS VARCHAR(20))

    PRINT ERROR_MESSAGE()

    PRINT ERROR_SEVERITY()

    PRINT ERROR_STATE()

END CATCH

GO

 

输出结果:

 997755.com澳门葡京 2

 

b)  如故地点的更新操作,发生错误,不进行后续代码

实行语句:

BEGIN TRY

    UPDATE tbOrder SET OrderAmount = ‘ABC’ WHERE OrderNo =
‘201605010001’

    PRINT ‘UPDATE ‘ + CAST(@@ERROR AS VARCHAR(20))

END TRY

BEGIN CATCH

    PRINT ‘CATCH ‘ + CAST(@@ERROR AS VARCHAR(20))

    PRINT ERROR_【997755.com澳门葡京】存款和储蓄进度的选取,Error使用简便小结。MESSAGE()

    PRINT ERROR_SEVERITY()

    PRINT ERROR_STATE()

END CATCH

GO

 

输出结果:

 997755.com澳门葡京 3

 

说明:在Try中施行SQL发生错误后,直接被Catch捕获,Try中承接代码终止实施,间接实践Catch中的代码

 

(4)  测试有东西的操作是不是爆发错误后都回滚

a)  直接扩充事物

推行脚本:

BEGIN TRAN

    –奉行常规

    INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )

       VALUES  ( ‘201605010001’,50,200,10)

 

    –推行报错

    DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

    PRINT ‘DELETE: ‘ +  CAST(@@ERROR AS VARCHAR(20))

 

COMMIT TRAN

 

实行结果(同时询问订单明细):

 997755.com澳门葡京 4

 

说明:施行出错后,前边实施的插入操作数据并未回滚,表达直接扩大事物并不可能回滚出错前的数量

 

b)  扩充@@Error决断试行是不是成功

实践脚本:

BEGIN TRAN

    –实施常规

    INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )

       VALUES  ( ‘201605010001’,50,200,10)

    IF @@ERROR <> 0

    BEGIN

       ROLLBACK TRAN

       RETURN

    END

 

    –试行报错

    DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

    –UPDATE tbOrder SET OrderAmount = ‘ABC’ WHERE OrderNo =
‘二零一六050一千一’   –将Delete操作换来更新操作发生十分后事物也会回滚

    IF @@ERROR <> 0

    BEGIN

       ROLLBACK TRAN

       RETURN

    END

 

COMMIT TRAN

 

实行结果(同时询问订单明细):

 997755.com澳门葡京 5

 

说明:扩展@@Error判别,实践错误时前边的数据都回滚了。同时将语句中的Delete操作换到实践已屏蔽的更新操作产生非常后,事物同样也会回滚

 

(5)  因而设置XACT_ABORT,测试出现谬误整个事物是还是不是回滚

备注:当 SET XACT_ABORT 为 ON 时,假若实行 Transact-SQL
语句发生运转时不当,则全体育赛事情将适可而止并回滚。

当 SET XACT_ABORT 为 OFF 时,有时只回滚爆发错误的 Transact-SQL
语句,而事情将承袭拓展管理。就算不当很要紧,那么就算 SET XACT_ABORT 为
OFF,也说不定回滚整个事情。OFF 是默许设置。

 

a)  XACT_ABORT 为 OFF,唯有进行出错的回滚

实施脚本:

SET XACT_ABORT OFF

BEGIN TRAN

    –施行例行

    INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )

       VALUES  ( ‘201605010001’,50,200,10)

 

    –实施报错

    DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

    PRINT ‘DELETE: ‘ +  CAST(@@ERROR AS VARCHAR(20))

 

    –试行平常

    INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )

       VALUES  ( ‘201605010001’,51,10,100)

   

COMMIT TRAN

 

推行结果(同时询问明细):

 997755.com澳门葡京 6

 

b)  XACT_ABORT 为 ON,强制整个事物回滚

进行脚本:

SET XACT_ABORT ON

BEGIN TRAN

    –执行常规

    INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )

       VALUES  ( ‘201605010001’,50,200,10)

 

    –推行报错

    DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

    PRINT ‘DELETE: ‘ +  CAST(@@ERROR AS VARCHAR(20))

 

COMMIT TRAN

SET XACT_ABORT OFF

实践结果(同时询问明细):

 997755.com澳门葡京 7

说明:设置XACT_ABORT为OFF(默感到OFF),唯有施行出错的说话回滚了,别的的未有回滚数据;设置XACT_ABORT为ON时,当实行SQL爆发错误后,强制整个事物回滚,并且不在实施后续代码

 

(6)  由此Try Catch捕获错误,呈现事物实行错误,并回滚

实践脚本:

BEGIN TRAN

    BEGIN TRY

    –实施不荒谬

    INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )

       VALUES  ( ‘201605010001’,50,200,10)

   

    –实践报错

    DELETE FROM tbOrder WHERE OrderNo = ‘201605010001’

    –UPDATE tbOrder SET OrderAmount = ‘ABC’ WHERE OrderNo =
‘201605010001’

   

    COMMIT TRAN

   

END  TRY

BEGIN CATCH

    P奥德赛INT ‘施行错误’ + CAST(@@E福特ExplorerRO陆风X8 AS VALANDCHARAV4(20))

    PRINT ERROR_MESSAGE()

    PRINT ERROR_SEVERITY()

    PRINT ERROR_STATE()

    ROLLBACK TRAN –必须增添回滚,不然事物会一向挂死在哪儿

END CATCH

 

试行结果(同时询问订单明细):

 997755.com澳门葡京 8

IF OBJECT_ID(‘PROC1’) IS NOT NULL

交付,成为数据库中的长久组成都部队分。假若事情境遇错误且必须撤回或回滚,则装有

3.sp_addmessage

自定义错误号

EXEC sp_addmessage  
    @msgnum = 60000,  
    @severity = 16,  
    @msgtext = N'Manual cast wrong ',
    @lang = 'us_english'; 

EXEC sp_addmessage  
    @msgnum = 60000,  
    @severity = 16,  
    @msgtext = N'手动抛错',  
    @lang = '简体中文';

在意:自定义错误号必须高于50000

1.三  总括表明

参考上边包车型大巴选取演示及结果,能够由如下三种管理格局确认保障数据完整性

(一) 通过@@Error剖断来讲话是还是不是推行成功,是或不是事物须求回滚(参见一.二 (四) )

(2) 设置XACT_ABORT为ON,强制整个事物实践出错开上下班时间都回滚 (参见一.二 (伍) )

(三) 通过Try Catch捕获实施分外,并回滚事物 (参见壹.二 (陆) )

 

    DROP PROCEDURE dbo.PROC1;

数据变动均被免除。

调用存款和储蓄进程

一.肆  参考资料

 微软官方网站解释

try catch 捕获不到的一对荒谬及消除措施

专门的学业执市价况追踪分析

 

GO

业务三种运营方式:
活动提交业务
每条单独的口舌都以贰个作业。
显式事务
各个业务均以 BEGIN TRANSACTION 语句显式开端,
以 COMMIT 或 ROLLBACK 语句显式停止。
隐性事务
在前贰个政工完毕时新业务隐式运营,但种种工作仍以 COMMIT 或 ROLLBACK 语句

一.查询存款和储蓄进程

----查询存储过程
CREATE PROCEDURE  Pro_score
(@Option VARCHAR(50),
 @name VARCHAR(50)='',
 @months INT=''
)
AS
BEGIN

---查询指定人分数
IF @Option='GetScore'
   BEGIN
        SELECT name,
               score
        FROM score
        WHERE name=@name

   END

----查询指定月份最高分数
IF @Option='MonthMaxScore'
   BEGIN
        SELECT Top 1 
             name,
             score
        FROM score
        WHERE months=@months
        ORDER BY score

   END



END

调用存款和储蓄进度:

EXEC Pro_score @Option='GetScore',@name='li'
EXEC Pro_score @Option='MonthMaxScore',@months=11

997755.com澳门葡京 9

1.五  相关附属类小部件

 相关SQL脚本

 

CREATE PROCEDURE PROC1

显式实现。

3.改动存款和储蓄进程

CREATE PROCEDURE [dbo].[Pro_Insert_score]
(@Option VARCHAR(50),
@name VARCHAR(50)='',
@months INT=0,
@score INT=0
) 
AS
BEGIN
DECLARE @ErrorMessage NVARCHAR(4000)
DECLARE @ErrorSeverity INT
DECLARE @ErrorState INT
 IF @Option='InsertScore'
     BEGIN

        -----使用事务
        BEGIN TRY  
                BEGIN TRAN 
                INSERT INTO score(name,score,months) 
                VALUES(@name,@score,@months)

                ----插入重复值报错事务回滚
                INSERT INTO score(name,score,months) 
                VALUES(@name,@score,@months)

                COMMIT TRAN  
                ----执行成功
                RETURN 0
            END TRY  
            BEGIN CATCH 
                IF @@TRANCOUNT > 0
                    ROLLBACK TRAN
                SELECT  @ErrorMessage = ERROR_MESSAGE(),@ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
                RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState) ;
                ----执行失败
                RETURN 1
            END CATCH

     END

END

调用存款和储蓄进度

----调用存储过程2
DECLARE @status INT
EXEC @status=Pro_Insert_score @Option='InsertScore',@name='chen',@months=12,@score=90
SELECT @status

997755.com澳门葡京 10

可以发现使用RAISE揽胜RO揽胜极光抛错出来的行号和音非非确定性信号都以荒谬的,五千0以此音讯号其实是不设有的,它是保存的二个统一的消息号。

能够经过询问sys.message查询对应的音信号

SELECT * FROM score WHERE name='chen'
SELECT * FROM sys.messages WHERE message_id=2601 and language_id=2052

997755.com澳门葡京 11

AS

事务操作的语法:

 肆.手动抛错中断

手动抛错也是这篇小说首要要讲的三个知识点,在有1部分业务场景在那之中有1对表明操作必要在数据库中进行,乃至必须在更新之后进展但是又是例行的提交操作,在那种场所下就须要手动举行求证是不是须求实践上面包车型地铁代码。,见过众多技术员写存款和储蓄过程喜欢在每3个决断的地方加上RETUCR-VN操作,目的是为了不实施后边的代码,同时又在RETUOdysseyN前增加ROLLBACK操作。那尽管是一个艺术,不过在事情中采取RETU哈弗N是二个很惊恐的操作,弄倒霉会导致专门的学问一贯处于展开操作变成表一贯被锁住,在调换处境是很惊恐的操作。

建议使用THROW来手动进行抛错,THROW抛错会约等于触发二个1一-1九等第的荒谬,那样会跳到CATCH中做ROLLBACK操作。

留意:THROW前务必以分行初叶,若是THROW前有代码以分行结尾也能够。

CREATE PROCEDURE [dbo].[Pro_score_throw]
(@Option VARCHAR(50),
 @name VARCHAR(50)='',
 @months INT=0,
 @score INT=0
) 
AS
BEGIN
DECLARE @ErrorNum INT,@ErrorSeverity INT,@ErrorState INT,@ErrorLine INT,@ErrorPro VARCHAR(200),@ErrorMessage NVARCHAR(4000);
IF @Option='UpdateScore'
    BEGIN

             -----使用事务
                  BEGIN TRY  
                        BEGIN TRAN 
                        UPDATE score
                        SET score=score+@score
                        WHERE name=@name AND months=@months

                        ----在有些业务场景有些判断必须等操作完了才能去做判断是否能继续执行下去
                        IF (SELECT score FROM score WHERE name=@name AND months=@months)>100
                        BEGIN

                             ;THROW 60000,'分数不能大于100',111 

                        END
                        COMMIT TRAN  

                    END TRY  
                    BEGIN CATCH 

                     ROLLBACK TRAN
                        ;THROW
                    END CATCH

        ----执行成功
        RETURN 0
    END

END

调用存款和储蓄进度

DECLARE @status INT
EXEC @status=Pro_score_throw @Option='UpdateScore',@name='chen',@months=10,@score=40
SELECT @status

997755.com澳门葡京 12

5.存款和储蓄进度调用存款和储蓄进程

CREATE TABLE Tbtran
(Id INT NOT NULL PRIMARY KEY,
Name VARCHAR(10)
)

INSERT INTO Tbtran(Id,Name) VALUES(1,'a'),(2,'b')

创办存款和储蓄进程

CREATE PROC SpChangeTranCall
(@Option VARCHAR(50),
@Id INT =NULL,
@Name VARCHAR(50)=NULL OUTPUT
)
AS
DECLARE @ErrorMessage NVARCHAR(4000)
DECLARE @ErrorSeverity INT
DECLARE @ErrorState INT
DECLARE @ReturnNum  INT ---Return返回值
DECLARE @OutputName VARCHAR(50)
BEGIN
SET XACT_ABORT ON   
IF @OPTION='a'
   BEGIN
           SELECT 
                @Name=Name
           FROM Tbtran
           WHERE Id=@Id

           IF @Name='a'
           BEGIN
                RETURN 2
           END
           IF @Name='b'
           BEGIN
                RETURN 3
           END

          INSERT INTO Tbtran(Id) VALUES(1)
    END
IF @OPTION='b'
   BEGIN
        BEGIN TRY  
            BEGIN TRAN  

            INSERT INTO Tbtran(Id,Name) VALUES(3,'c');

            ----调用存储过程,内部存储过程不使用事务
            EXEC @ReturnNum=SpChangeTranCall @OPTION='a',@Id=@Id,@Name=@OutputName OUTPUT
            ---接收内部存储过程OUTPUT返回值
            SELECT @OutputName
            ---判断调用存储过程是否执行成功
            IF @ReturnNum>0
            BEGIN
                 ROLLBACK TRAN
                 RETURN  @ReturnNum
            END

            COMMIT TRAN 
            ---成功标志,放在COMMIT后
            RETURN 0 
        END TRY  
        BEGIN CATCH  
            IF @@TRANCOUNT > 0
                ROLLBACK TRAN
            SELECT @ErrorMessage = ERROR_MESSAGE(),@ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); 
            RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState) 
            ---失败标志,放在最后
            RETURN 1
        END CATCH 
    END 
END

调用存款和储蓄进度

DECLARE @a INT
SET @a=-2
EXEC @a=SpChangeTranCall @OPTION='b',@Id=1
SELECT @a AS ReturnNum

997755.com澳门葡京 13

储存进程调用存储进度事务的三种管理措施:

1.之中存款和储蓄进程不要包罗事务,因为中间ROLLBACK会直接回滚到表面包车型大巴BEGIN
TRAN导致表面包车型大巴ROLLBACK没有对应的COMMIT;

二.还有①种格局是在调用内部存款和储蓄进度以前使用保存点“SAVE TRAN
TRAN1”,同时内部存款和储蓄进程的ROLLBACK TRAN必须钦赐专门的学业保存点,比如“ROLLBACK
TRAN TRAN1”,那样内部存款和储蓄过程回滚就只会回滚到保险点.

三.在表面存款和储蓄进度的CATCH块的ROLLBACK前拉长IF @@TRANCOUNT > 0判别标准

 

假如不要求采用RETUPAJERON
一来注脚实施倒闭,能够采用THROW来取代RAISE福特ExplorerROTiggo来接受再次回到的错误值

ALTER PROC SpChangeTranCall
(@Option VARCHAR(50),
@Id INT =NULL,
@Name VARCHAR(50)=NULL OUTPUT
)
AS
DECLARE @ReturnNum  INT ---Return返回值
DECLARE @OutputName VARCHAR(50)
BEGIN
SET XACT_ABORT ON   
IF @OPTION='a'
   BEGIN
           SELECT 
                @Name=Name
           FROM Tbtran
           WHERE Id=@Id

           IF @Name='a'
           BEGIN
                RETURN 2
           END
           IF @Name='b'
           BEGIN
                RETURN 3
           END

          INSERT INTO Tbtran(Id) VALUES(1)
    END
IF @OPTION='b'
   BEGIN
        BEGIN TRY  
            BEGIN TRAN  

            INSERT INTO Tbtran(Id,Name) VALUES(3,'c');

            ----调用存储过程,内部存储过程不使用事务
            EXEC @ReturnNum=SpChangeTranCall @OPTION='a',@Id=@Id,@Name=@OutputName OUTPUT
            ---接收内部存储过程OUTPUT返回值
            SELECT @OutputName
            ---判断调用存储过程是否执行成功
            IF @ReturnNum>0
            BEGIN
                 ROLLBACK TRAN
                 RETURN  @ReturnNum
            END

            COMMIT TRAN 
            ---成功标志,放在COMMIT后
            RETURN 0 
        END TRY  
        BEGIN CATCH  
            IF @@TRANCOUNT > 0
                ROLLBACK TRAN
            ;THROW
        END CATCH 
    END 
END

调用存款和储蓄进度

DECLARE @a INT
SET @a=-2
EXEC @a=SpChangeTranCall @OPTION='b',@Id=3
SELECT @a AS ReturnNum

997755.com澳门葡京 14

留意:THROW接收的回到错误行是准确的失实行,而RAISEHummerH贰RO奥迪Q7重返的不当行是不得法的。

    BEGIN

BEGIN TRANSACTION
BEGIN DISTRIBUTED TRANSACTION
COMMIT TRANSACTION
COMMIT WORK
ROLLBACK WORK
SAVE TRANSACTION
BEGIN TRANSACTION

陆.事务嵌套事务的敞亮

---事务1
BEGIN TRAN
        ---事务2
        BEGIN TRAN

        COMMIT TRAN /ROLLBACK TRAN 

COMMIT TRAN /ROLLBACK TRAN 

对此事情嵌套事务,事务二的ROLLBACK操作会直接回滚到事务1的BEGIN
TRAN,会促成事务一的ROLLBACK未有相应的BEGIN
TRAN。管理情势能够在调用事务二此前定义八个事情保存点也许在事务1的ROLLBACK前拉长IF
@@TRANCOUNT > 0推断标准是或不是留存工作须要回滚。

        BEGIN TRY

BEGIN TRANSACTION
标记3个显式本地职业的伊始点。

7.SET XACT_ABORT ON

并不是颇具的错误都能被CATCH所接收。对于严重等第为0-10(音讯性音讯)和20-二五(致命的新闻)是无法被CATCH所接收的,那时如若在作业中相见了那类的报错那么通用会招致事务管理张开状态,这时就必要展开XACT_ABORT。当开启XACT_ABORT后1旦代码中留存报错就会实行回滚操作,而不管错误的等级。比如:

CREATE TABLE [dbo].[AA](
    [id] [int] NULL
) ON [PRIMARY]
GO
CREATE PROC Pro_bb
(@Option VARCHAR(50))
AS
BEGIN
IF @OPTION='a'
   BEGIN
       TRUNCATE TABLE AA;
       SELECT * FROM AA;
        ----事务1
        BEGIN TRY  
            BEGIN TRAN  
                 INSERT INTO AA SELECT 2  
                 SELECT * FROM AA;
                 INSERT INTO #BB SELECT 1 
            COMMIT TRAN;  
        END TRY  
        BEGIN CATCH  
            IF @@TRANCOUNT > 0
            ROLLBACK TRAN;  
            ;THROW
        END CATCH 
    END
END

鉴于目前表#BB不存在,导致插入报错,可是严重等第又小于11导致CATCH接收不到错误,那时查看开采事情处于张开状态,而且表AA也被锁住。

EXEC Pro_bb @OPTION='a';
DBCC OPENTRAN;

997755.com澳门葡京 15

充裕作业前拉长 SET XACT_ABORT ON  

ALTER TABLE [dbo].[AA](
    [id] [int] NULL
) ON [PRIMARY]
GO
CREATE PROC Pro_bb
(@Option VARCHAR(50))
AS
BEGIN
IF @OPTION='a'
   BEGIN
   SET XACT_ABORT ON  
       TRUNCATE TABLE AA;
       SELECT * FROM AA;
        ----事务1
        BEGIN TRY  
            BEGIN TRAN  
                 INSERT INTO AA SELECT 2  
                 SELECT * FROM AA;
                 INSERT INTO #BB SELECT 1 
            COMMIT TRAN;  
        END TRY  
        BEGIN CATCH  
            IF @@TRANCOUNT > 0
            ROLLBACK TRAN;  
            ;THROW
        END CATCH 
    END
END

再一次实行

EXEC Pro_bb @OPTION='a';
DBCC OPENTRAN;

997755.com澳门葡京 16

从不处于打开的事务而且工作也实行了回滚操作。

            BEGIN TRAN;

BEGIN TRANSACTION将 @@TRANCOUNT 加 1。

总结

1.THROW背后的语句不会被实行;如若不需求Return 0和Return
1来作为成功战败的注明那么能够行使THROW来顶替RAISEMuranoROGL450,不然使用RAISEPRADORO帕Jero。不要接纳THROW抛错又接纳RAISEBMWX伍RO本田UR-V来接过错误,在事情嵌套事务的写法中纵然内部事务使用RAISE奥德赛ROLAND来接收THROW再次来到的报错不会执行前面包车型大巴ROLLBACK。

二.提议在ROLLBACK前统OPPO上IF @@TRANCOUNT >
0推断标准,那样能够幸免因为内部的ROLLBACK回滚恐怕RETU陆风X8N操作导致ROLLBACK没有对号入座的COMMIT。

三.CATCH只是用来拍卖TBMWX3Y报错之后的逻辑,不要认为代码实施到了CATCH的ROLLBACK就会终结管理,除非是在ROLLBACK后插手了RETU福特ExplorerN可能THROW之类的中止代码试行的指令,不然代码还将继续实施ROLLBACK之后的代码以至END
CATCH之后的代码(如果存在)。

4.1旦存款和储蓄进程调用存款和储蓄进度,内部的贮存进度不接纳专门的学问也不须要使用T奥迪Q伍Y来接收错误,能够参见上面包车型大巴“伍.存款和储蓄进度调用存款和储蓄进度”。

伍.尽管OUTPUT也能用来收纳存储进程的执汇兑况,可是RETU智跑N的作用能够跳出存款和储蓄进程不施行前边的代码,所以制止固然用RETU帕杰罗N作为奉行成功失败的申明又选拔OUTPUT来注脚实施成功和败北的符号,OUTPUT越多用来回到内部存款和储蓄进度试行结果的值而不是用来做成功失利的标识。

 

 

 

备注:

    作者:pursuer.chen

    博客:http://www.cnblogs.com/chenmh

本站点所有随笔都是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接,否则保留追究责任的权利。

《欢迎交流讨论》

 

            SELECT  ‘Tran1’ ,1;

BEGIN
TRANSACTION 代表一点,由一连引用的数码在该点是逻辑和物理上都平等的。假设遇上错误,在 BEGIN
TRANSACTION 之后的兼具数据变动都能实行回滚,以将数据再次回到到已知的同样状态 。各个业务继续执行直到它科学地形成而且用 COMMIT
TRANSACTION 对数据库作永世的变动,恐怕遇上错误并且用 ROLLBACK
TRANSACTION 语句擦除全部改造

            RAISERROR(16,1,1);

语法
BEGIN TRAN [ SACTION ] [ transaction_name | @tran_name_variable [
WITH MARK [ ‘description’ ] ] ]

            SELECT  ‘Tran1’ ,2;

例子:
BEGIN TRAN T1
UPDATE table1 …
–nest transaction M2
BEGIN TRAN M2 WITH MARK
UPDATE table2 …
SELECT * from table1
COMMIT TRAN M2
UPDATE table3 …
COMMIT TRAN T1

            COMMIT TRAN;

BEGIN DISTRIBUTED TRANSACTION
点名二个由 Microsoft 遍布式事务管理和煦器 (MS
DTC) 管理的 Transact-SQL 布满式事务的胚胎。

        END TRY

语法
BEGIN DISTRIBUTED TRAN [ SACTION ]
[ transaction_name | @tran_name_variable ]

        BEGIN CATCH

参数
transaction_name
是用户定义的事务名,用于跟踪 MS
DTC 实用工具中的布满式事务。 transaction_name 必须符合标志符规则,可是仅使用头 3贰 个字符

   SELECT  ‘Tran1’ ,3;

@tran_name_variable
是用户定义的3个变量名,它富含3个事务名,该事务名用于追踪 MS
DTC 实用工具中的布满式事务。必须用 char、varchar、nchar 或 nvarchar 数据类型注明该变量。

            ROLLBACK TRAN;

注释
实行BEGIN DISTXC90IBUTED
TRANSACTION 语句的服务器是业务创制人,并且决定作业的姣好

            SELECT  ‘Tran1’ ,4;

当连接发出后续 COMMIT TRANSACTION 或 ROLLBACK TRANSACTION 语句时,
主要控战胜务器请求 MS DTC 在所涉及的劳务器间管理遍布式事务的形成。
有七个格局可将长途 SQL 服务器登记在1个布满式事务中:

            RETURN -1;

分布式事务中已登记的再而三执行贰个长途存款和储蓄进程调用,该调用引用2个中远距离服务器。 
布满式事务中已登记的总是实行1个遍及式查询,该查询引用二个长途服务器。

        END CATCH;

示例
本例在该地和长距离数据库上更新小编的姓。本地和远程数据库将同时提交或同时回滚本作业。

 

说明 
此时此刻的SQL Server 上必须安装 MS DTC.

    END;

USE pubs
GO
BEGIN DISTRIBUTED TRANSACTION
UPDATE authors
SET au_lname = ‘McDonald’ WHERE au_id = ‘409-56-7008’
EXECUTE link_Server_T.pubs.dbo.changeauth_lname
‘409-56-7008′,’McDonald’
COMMIT TRAN
GONote:
万壹急需一而再远程DB,借使是linkServer 格局连接的话,一定要修该linkServer的 RPC 选项置为 True。

GO

SET XACT_ABORT
点名当 Transact-SQL 语句产生运营时不当时,Microsoft? SQL
Server? 是或不是自动回滚当前作业。

 

( 能够相比简单的通晓,假若中间有此外一句SQL 出错,全部SQL全体回滚.特别适用于 Procedure 中间调用Procedure ,假若第3个Procedure
Ok,被调用的Procedure 中间有荒唐,要是SET
XACT_ABORT=false,则失误的部分回滚,别的一些交给,当然外部Procedure 也交给。).

实行一下,抛出荒唐后一而再向下试行。

—在分布式Trans中毫无疑问要小心设置上边参数(XACT_ABORT)

997755.com澳门葡京 17

语法SET XACT_ABORT { ON | OFF }

 997755.com澳门葡京 18

注释 当 SET
XACT_ABORT 为 ON 时,假若 Transact-SQL 语句发生运营时不当,整个业务将终止并回滚。为 OFF 时,只回滚发生错误的Transact-SQL语句,而职业将持续张开始拍录卖。编写翻译错误(如语法错误)不受 SET
XACT_ABORT 的影响。

 

对于绝大多数 OLE DB 提供程序(包括 SQL
Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON。

 

SET XACT_ABORT 的设置是在实行或运营时设置,而不是在分析时设置。

 

示例 下例导致在蕴藏别的 Transact-SQL 语句的工作中发生违反外键错误。在第二个语句聚集发生错误,但别的语句均成功实践且专业成功
付出。在第二个语句聚焦,SET
XACT_ABORT 设置为 ON。那致使语句错误使批管理终止,并使职业回滚。

当工作有嵌套的时候。在抛出荒唐的作业里面,会继续执行批管理剩下的说话,最终才回滚上去并往上层抛错误。非抛出层和最外层事务,语句运营至rollback就往上层抛。

CREATE TABLE t1 (a int PRIMARY KEY)
CREATE TABLE t2 (a int REFERENCES t1(a))
GO
INSERT INTO t1 VALUES (1)
INSERT INTO t1 VALUES (3)
INSERT INTO t1 VALUES (4)
INSERT INTO t1 VALUES (6)
GO
SET XACT_ABORT OFF
GO
BEGIN TRAN
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) /* Foreign key error */
INSERT INTO t2 VALUES (3)
COMMIT TRAN
GO

如下

SET XACT_ABORT ON
GO

 

BEGIN TRAN
INSERT INTO t2 VALUES (4)
INSERT INTO t2 VALUES (5) /* Foreign key error */
INSERT INTO t2 VALUES (6)
COMMIT TRAN
GO

 

SAVE TRANSACTION
在事行业内部安装保存点。

IF OBJECT_ID(‘PROC2’) IS NOT NULL

语法 SAVE TRAN [ SACTION ] { savepoint_name |
@savepoint_variable }
参数 savepoint_name
是指派给保存点的称号。保存点名称必须符合标记符规则,但只利用前 3二 个字符。
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名号。
总得用 char、varchar、nchar 或 nvarchar 数据类型证明该变量。 注释
用户能够在专行业内部设置保存点或标记。保存点定义要是有规则地打消事务的一有些,事 务可以回到的职责。要是将业务回滚到保存点,则必须(假如需求,使用越来越多的 Transact-SQL 语句和 COMMIT
TRANSACTION 语句)继续产生工作,或然必须(通过将业务回滚到其早先点)完全裁撤事务。若要撤废全数事情,请使用 ROLLBACK
TRANSACTION transaction_name 格式。那将撤废事务的所 有说话和进度。

 DROP PROCEDURE dbo.PROC2

Note:1: 在由 BEGIN DISTRubiconIBUTED
TRANSACTION 显式运行或从地面职业进级而来的布满式事务中,不扶助 SAVE
TRANSACTION。

go

2:当专门的学业开首时,将平素调节作业中所使用的能源直到职业完结(也正是锁定)。当将职业的一有的回滚到保存点时,将一连调控财富直到职业完结(恐怕回滚全体事情)。

CREATE PROCEDURE PROC2

例子:begin transaction
save transaction A
insert into demo values(‘BB’,’B term’)
rollback TRANSACTION A
create table demo2(name varchar(10),age int)
insert into demo2(name,age) values(‘lis’,1)
commit transaction

AS

ROLLBACK TRANSACTION

BEGIN

将显式事务或隐性事务回滚到事情的源点或事行业内部的某部保存点。
语法
ROLLBACK [ TRAN [ SACTION ]
[ transaction_name | @tran_name_variable | savepoint_name |
@savepoint_variable ] ]

 BEGIN TRY

参数
transaction_name
是给 BEGIN
TRANSACTION 上的事情指派的名称。transaction_name 必须符合标记符规则,但只使用工作名称的前 3二 个字符。嵌套
事务时,transaction_name 必须是缘于最远的 BEGIN
TRANSACTION 语句的名称。
@tran_name_variable
是用户定义的、含有有效专门的学业名称的变量的称呼。必须用 char、varchar、nchar 或 nvarchar 数据类型表明该变量。
savepoint_name
是来自 SAVE
TRANSACTION 语句的 savepoint_name。savepoint_name 必须符合标志符规则。当规则回滚只影响专门的学问的1有个别时使 用savepoint_name。
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名目。必须用 char、varchar、nchar 或 nvarchar 数据类型申明该变量。

 BEGIN TRAN

注释 ROLLBACK
TRANSACTION 清除自事务的起源或到有些保存点所做的具有数据修改。ROLLBACK 还释放由业务调整的能源。
不带 savepoint_name 和 transaction_name 的 ROLLBACK
TRANSACTION 回滚到事情的源点。嵌套事务时,该语句将持有内层事务回滚到 最远的BEGIN
TRANSACTION 语句。在那二种意况下,ROLLBACK
TRANSACTION 均将 @@TRANCOUNT 系统函数减为 0。ROLLBACK 
TRANSACTION savepoint_name 不减少 @@TRANCOUNT。

  SELECT ‘Tran2’,1

Note: 
ROLLBACK TRANSACTION 语句若钦点 savepoint_name 则不自由别的锁。
在由 BEGIN DIST路虎极光IBUTED
TRANSACTION 显式运行或从本地职业升级而来的布满式事务中,ROLLBACK
TRANSACTION 无法
引用savepoint_name。在奉行 COMMIT
TRANSACTION 语句后不能够回滚事务

  EXEC dbo.PROC1

在职行业内部允许有双重的保存点名称,但 ROLLBACK
TRANSACTION 若使用重复的保存点名称,则只回滚到近期的利用该保存点名称的SAVE
TRANSACTION。

  SELECT ‘Tran2’,2

在储存进度中,不带 savepoint_name 和 transaction_name 的 ROLLBACK
TRANSACTION 语句将具有语句回滚到最远的 BEGINTRANSACTION。在存款和储蓄进度中,ROLLBACK
TRANSACTION 语句使 @@TRANCOUNT 在触发器达成时的值差别于调用该存款和储蓄进程时的@@TRANCOUNT 值,并且生成2个消息。该新闻不影响前边的管理。

 COMMIT TRAN

设若在触发器中发生 ROLLBACK
TRANSACTION:将回滚对方今职业中的那一点所做的持有数据修改,包含触发器所做的修改。 
触发器继续实行 ROLLBACK 语句之后的全数其余语句。假若那几个语句中的任性语句修改数据,则不回滚那么些修改。实施别的的语句不会激起嵌套触发器。在批管理中,不实行全体位于激发触发器的口舌之后的口舌。每一遍进入触发器,@@TRANCOUNT 就充实 一,固然在机动提交形式下也是那样。(系统将触发器视作隐性嵌套事务。)

 END TRY

在仓库储存进度中,ROLLBACK
TRANSACTION 语句不影响调用该进程的批管理中的后续语句;
将实践批管理中的后续语句。在触发器中,ROLLBACK
TRANSACTION 语句终止含有刺激触发器的语句的批管理;
不实施批管理中的后续语句。

 BEGIN CATCH

ROLLBACK TRANSACTION
语句不转移显示给用户的音信。借使在蕴藏过程或触发器中要求告诫,请使用
RAISEEscortROOdyssey 或 PSportageINT 语句。RAISE奇骏ROGL450 是用来建议错误的首荐语句。

  SELECT ‘Tran2’,3

ROLLBACK 对游标的震慑由上面八个规则定义: 
当 CURSOR_CLOSE_ON_COMMIT 设置为 ON 时,ROLLBACK
关闭但不自由具备展开的游标。 
当 CURSOR_CLOSE_ON_COMMIT 设置为 OFF 时,ROLLBACK
不影响其余打开的一齐 STATIC 或 INSENSITIVE 游标不影响已完全填充的异步
STATIC 游标。将关闭但不自由别的其余品类的开垦的游标。 
对此变成终止批管理并扭转内部回滚的一无所能,将释放在含蓄该错误语句的批管理内表明的保有游标。
随便游标的门类或 CUCR-VSORAV4_CLOSE_ON_COMMIT
的安装,全体游标均将被放出,在这之中包蕴在该错误批处理所调用的储存进度内申明的游标。在该错误批管理在此之前的批处理内注解的游标以规则
一 和 2 为准。死锁错误就属于那类错误。在触发器中发出的 ROLLBACK 语句也
自动生成这类错误。

  ROLLBACK TRAN

权限
ROLLBACK TRANSACTION 权限默许授予任何有功效户。
例子:

  SELECT ‘Tran2’,4

begin transaction
save transaction A
insert into demo values(‘BB’,’B term’)
rollback TRANSACTION A

  RETURN -2

— select * into demo2 from demo1

 END CATCH

create table demo2(name varchar(10),age int)
insert into demo2(name,age) values(‘lis’,1)
rollback transaction

END

COMMIT TRANSACTION
标记二个打响的隐性事务或用户定义事务的甘休。要是 @@TRANCOUNT 为 一,COMMIT

GO

TRANSACTION 使得自从工作开端以来所实践的 全数数据修改成为数据库的永世部分,释放连接

 

占有的财富,并将 @@TRANCOUNT 减弱到 0。借使@@TRANCOUNT 大于 1,则COMMIT

 

TRANSACTION 使 @@TRANCOUNT 按 1 递减。

IF OBJECT_ID(‘PROC3’) IS NOT NULL

唯有当事务所引用的装有数据的逻辑都没有错开上下班时间,发出 COMMIT
TRANSACTION 命令。
COMMIT WORK
标明职业的竣事。
语法
COMMIT [ WORK ]

 DROP PROCEDURE dbo.PROC3

注释
此语句的效劳与 COMMIT TRANSACTION 同样,但 COMMIT
TRANSACTION 接受用户定义的事体

go

名称。那几个钦赐或尚未点名可选关键字WO大切诺基K 的 COMMIT 语法与 SQL-九2 包容

CREATE PROCEDURE PROC3

例子
begin transaction a
insert into demo values(‘BB’,’B term’)
commit TRANSACTION A

AS

隐性事务
当连接以隐性事务格局展开操作时,SQL
Server就要付出或回滚当前事务后自动运转新业务。无须描述事务的早先,只需提交或

BEGIN

回滚各类业务。隐性事务格局调换连续的事务链。

 BEGIN TRY

在为总是将隐性事务格局设置为张开之后,当 SQL
Server 第3回实行下列任何语句时,都会活动运转一个作业:

 BEGIN TRAN

 

ALTER TABLE

INSERT

 

CREATE

OPEN

 

DELETE

REVOKE

 

DROP

SELECT

 

FETCH

TRUNCATE TABLE

 

GRANT

UPDATE

  SELECT ‘PROC3’,1

在发出 COMMIT 或 ROLLBACK 语句以前,该业务将一贯保持有效。在首先个工作被交付或回滚之后,下次当连接实践那几个讲话

  EXEC dbo.PROC2

中的任何语句时,SQL Server 都将机关运转1个新工作。SQL
Server 将不断地生成贰个隐性事务链,

  SELECT ‘PROC3’,2

直至隐性事务情势关闭甘休

 COMMIT TRAN

例子:
begin transaction 
save transaction A

 END TRY

insert into demo values(‘BB’,’B term’)
rollback TRANSACTION A

 BEGIN CATCH

create table demo2(name varchar(10),age int)
insert into demo2(name,age) values(‘lis’,1)
rollback transaction
— 在 Create table demo二 时 SQL
Server 已经隐式制造贰个Trans,知道提交或回滚

  SELECT ‘PROC3’,3

嵌套事务管理:

  ROLLBACK TRAN

1: Trans 嵌套,将内部的trans 合并到表面并摇身壹变一个Trans.

  SELECT ‘PROC3’,4

begin tran t1

  RETURN -3

—-In the first trans .
Insert into demo2(name,age) values(‘lis’,1)

 END CATCH

—Second Trans begin transaction t2 
insert into demo values(‘BB’,’B term’)
commit transaction t2

END

—-In the first trans .
Insert into demo2(name,age) values(‘lis’,2)
rollback transaction t1

GO

Note:

 

在一文山会海嵌套的事务中用三个事情名给八个事情命名对该业务未有啥样震慑。系统仅登记第四个(最外部的)事务名。回滚

实践存款和储蓄进度

到任何任何名字(有效的保存点名除此之外)都会发出错误。

SET NOCOUNT ON;

实际,任何在回滚在此之前实践的言辞都未曾在错误爆发时回滚。那语句仅当外层的事务回滚时才会开始展览回滚。

DECLARE @INT INT

例:内部事务回滚SQL server 报错。

EXEC @INT=dbo.PROC3

begin tran t1 
Insert into demo2(name,age) values(‘lis’,1)
—Second Trans

SELECT @INT

–Server: Msg 6401, Level 16, State 1, Line 6
—Cannot roll back t2. No transaction or savepoint of that name was
found.
begin transaction t2 
insert into demo values(‘BB’,’B term’)
rollback transaction t2

 

—-In the first trans .
Insert into demo2(name,age) values(‘lis’,2)
commit transaction t1

997755.com澳门葡京 19

例: 内部事务提交SQL server 不会报错。

 

begin tran t1 
Insert into demo2(name,age) values(‘lis’,1)
—Second Trans no error
begin transaction t2 
insert into demo values(‘BB’,’B term’)
commit transaction t2

 

—-In the first trans .
Insert into demo2(name,age) values(‘lis’,2)
commit transaction t1

 

SQL Server 的割裂等第:

rollback在嵌套触发器中,借使在触发器的政工里面抛出荒谬,回滚以前触发器的言语修改,继续试行rollback之后的言辞。但并不会激活之后的触发器

1: 设置TimeOut 参数

 

Set Lock_TimeOut 5000

CREATE TABLE TestTR

被锁超时5秒将活动解锁

(

Set Lock_TimeOut 0

 ID INT PRIMARY KEY,

产立时解锁,再次来到Error 默感到-一,Infiniti等待

 Name NVARCHAR(50)

2:

)

(SET TRANSACTION ISOLATION LEVEL
{ READ COMMITTED
| READ UNCOMMITTED
| REPEATABLE READ | SERIALIZABLE})

 

READ COMMITTED

CREATE TABLE TRTB1

钦赐在读取数据时间调整制共享锁以免止脏读,但数量可在工作截至前改换,从而发出不可重复读取或

(

幻像数据。该选项是SQL Server 的私下认可值。

 ID INT PRIMARY KEY,

幸免脏读,并在别的session 在事情中不能够对已有数量实行修改。共享锁。

 Col1 INT

READ UNCOMMITTED

)

实践脏读或 0 级隔开锁定,那象征不爆发共享锁,也不接受排它锁。当设置该选项时,能够对数

 

据施行未提交读或脏读;在作业结束前可以变动数据内的数值,行也得以出现在多少汇总或从数据

CREATE TRIGGER TR_TESTTR1 ON dbo.TestTR AFTER

集消失。该选取的功能与在事情内具有语句中的全体表上设置 NOLOCK 同样。那是八个隔绝品级中

INSERT AS

范围最小的等级。

BEGIN TRY

REPEATABLE READ

BEGIN TRAN

锁定查询中应用的有着数据避防止其余用户更新数据,不过别的用户能够将新的幻影行插入数据

 INSERT INTO dbo.TRTB1

集,且幻像行包罗在此时此刻业务的后续读取中。因为并发低于默许隔断品级,所以应只在须求时才使

   ( ID, Col1 )

用该选项。

 VALUES  ( 1,

SERIALIZABLE

     CONVERT(INT,’a’) )

在数码集上放置3个限制锁,以幸免别的用户在业务实现在此之前更新数据集或将行插入数据集内。那

COMMIT TRAN

是多少个隔开分离品级中限制最大的等级。因为并发等级很低,所以应只在须要时才使用该选项。该选项

END TRY

的机能与在事情内部存款和储蓄器有 SELECT 语句中的全部表上设置 HOLDLOCK 一样。

BEGIN CATCH

 ROLLBACK TRAN

 INSERT INTO dbo.TestTR

         ( ID, Name )

 VALUES  ( 1,

     CONVERT(INT,’2′) )

END CATCH

GO

 

 

INSERT INTO TestTR ( ID, Name )

 VALUES  ( 4,

     CONVERT(INT,’3′) )

 

 

997755.com澳门葡京 20

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website