none
如果需要在存储过程的事务中创建数据库怎么办 RRS feed

  • 问题

  • 我是这样写的


    ALTER PROCEDURE [dbo].[NewObject]

    @ObjectData_Name Varchar(123)    --项目的数据库名称

    AS

    Declare @Error_Text varchar(254) , @Data_Num int , @SQL_Text Varchar(4000)
    Declare @ObjectData_Path Varchar(MAX)

    --查询数据库名称是否已经在使用
    Select @Data_Num = Count(*) From ( Select name From sys.databases ) as a Where a.name = @ObjectData_Name
    If @Data_Num > 0
            Begin
                    Set @Error_Text = '该数据库名称已使用,请修改后重试。'
                    GoTo RT1
            End

    --查询主数据库保存路径 用@ObjectData_Path保存
    Select @ObjectData_Path = SUBSTRING(physical_name, 1, CHARINDEX(N'ys_data', LOWER(physical_name)) - 1)
               FROM master.sys.master_files WHERE file_id = 1 AND name = 'ys_data'
    If @@error != 0
          Begin
              Set @Error_Text = '查询数据库保存路径时出错'
              GOTO RT1
          End

    Begin Transaction
            Begin
                    Set @SQL_Text = 'Create DataBase ' + @ObjectData_Name +
                            ' ON ( NAME = ' + @ObjectData_Name + '  , FILENAME = '''+
                            @ObjectData_Path + @ObjectData_Name + '_data.mdf'')'
                    Execute ( @SQL_Text )
                    If @@error != 0
                            Begin
                                    Set @Error_Text = '创建数据库时出错'
                                    GOTO RT1
                            End
            End

    ......省略


    Select 1
    Commit Transaction
    Return

    RT:
    ROLLBACK TRANSACTION
            Select -1 , @Error_Text
            Return

    RT1:

            Select -1 , @Error_Text
            Return


    出现这样的错误信息“在多语句事务内不允许使用 CREATE DATABASE 语句。”
    难道不能在存储过程中创建新数据库?
    如果想在事务中创建数据库怎么办?
    2009年9月30日 0:55

答案

  • Don't put it in transaction.
    2009年9月30日 2:14
  • CREATE DATABASE 语句必须以自动提交模式(默认事务管理模式)运行,不允许在显式或隐式事务中使用。

    BOL中明确的写了的,为什么偏要和MS对着干呢?



    事务中要是能够 创建文件并删除文件 多厉害啊
    hello
    2009年9月30日 2:20
  • Try with

    begin try
     ...
    end try

    begin catch
     ...
    end catch 
    2009年9月30日 3:02
  • 你可以这样做:
    1.你对数据库的任何一个操作都记录下来(用文本事实记录了到安装目录)
    2.这个时候如果你已经创建了数据库,比如database1
    3.在安装表的时候机器挂了(停电等原因)。
    4.重新安装(来电了,或者故障修复)
    5.检查已经安装的记录(就是步骤1记录的)按照相反的顺序回滚操作。删除数据库database1。或者一个好办法就是继续从刚刚没完成的地方开始继续执行安装下去。

    其实你做的记录,就有点类似事务了。呵呵

    这个的原理有点类似windows的安装过程(windows遇到停电啥的重启后会继续安装),或者vs的安装过程(vs的安装过程如果出错,可以完全回滚)。


    family as water
    2009年9月30日 3:40
  • 我的意思是这样:
    数据库创建后 再由事务创建表 在创建表的时候 如果发生比如 停电、死机等情况(客户的电脑不稳定的有的是),因为表的创建还没有提交所以重启后就回滚了,而已经创建的数据库还在,这个怎么处理。

    看看 MS 在BOL 联机丛书 上的官方示例吧(注意:这不是我写的。不负责哟):

    USE master;

     GO

    IF DB_ID (N'mytest') IS NOT NULL

    DROP DATABASE mytest;

    GO

    CREATE DATABASE mytest;

    GO


    这就叫 害死人不赔命

    hello

    2009年9月30日 5:55

全部回复

  • Don't put it in transaction.
    2009年9月30日 2:14
  • CREATE DATABASE 语句必须以自动提交模式(默认事务管理模式)运行,不允许在显式或隐式事务中使用。

    BOL中明确的写了的,为什么偏要和MS对着干呢?



    事务中要是能够 创建文件并删除文件 多厉害啊
    hello
    2009年9月30日 2:20


  • 事务中要是能够 创建文件并删除文件 多厉害啊

    看见这个明白了 谢谢


    但是 我想做到创建数据库后的操作出错后 也撤销数据库的创建 该怎么做
    2009年9月30日 2:52
  • Try with

    begin try
     ...
    end try

    begin catch
     ...
    end catch 
    2009年9月30日 3:02
  • Try with

    begin try
     ...
    end try

    begin catch
     ...
    end catch 

    是在存储过程中写这些吗?
    2009年9月30日 3:08
  • Yes, books online has sample code.
    2009年9月30日 3:10
  • try了估计也是报不能用显式事务的错误。
    2009年9月30日 3:13
    版主


  • 事务中要是能够 创建文件并删除文件 多厉害啊

    看见这个明白了 谢谢


    但是 我想做到创建数据库后的操作出错后 也撤销数据库的创建 该怎么做
    创建数据库后的操作出错后,就是说 没有创建数据库, 何需 “撤销数据库的创建” ?
    hello
    2009年9月30日 3:16
  • 我的意思是这样:
    数据库创建后 由事务创建表 在创建表的时候 如果发生比如 停电、死机等情况(客户的电脑不稳定的有的是),因为表的创建还没有提交所以重启后就回滚了,而已经创建的数据库还在,这个怎么处理。
    2009年9月30日 3:20
  • try了估计也是报不能用显式事务的错误。
    I think OP likes to catch any error after creating database.
    2009年9月30日 3:22


  • 事务中要是能够 创建文件并删除文件 多厉害啊

    看见这个明白了 谢谢


    但是 我想做到创建数据库后的操作出错后 也撤销数据库的创建 该怎么做
    创建数据库后的操作出错后,就是说 没有创建数据库, 何需 “撤销数据库的创建” ?
    hello
    Error to create database is different from error after creating database.
    2009年9月30日 3:23
  • 我的意思是这样:
    数据库创建后 再由事务创建表 在创建表的时候 如果发生比如 停电、死机等情况(客户的电脑不稳定的有的是),因为表的创建还没有提交所以重启后就回滚了,而已经创建的数据库还在,这个怎么处理。
    2009年9月30日 3:29
  • 你可以这样做:
    1.你对数据库的任何一个操作都记录下来(用文本事实记录了到安装目录)
    2.这个时候如果你已经创建了数据库,比如database1
    3.在安装表的时候机器挂了(停电等原因)。
    4.重新安装(来电了,或者故障修复)
    5.检查已经安装的记录(就是步骤1记录的)按照相反的顺序回滚操作。删除数据库database1。或者一个好办法就是继续从刚刚没完成的地方开始继续执行安装下去。

    其实你做的记录,就有点类似事务了。呵呵

    这个的原理有点类似windows的安装过程(windows遇到停电啥的重启后会继续安装),或者vs的安装过程(vs的安装过程如果出错,可以完全回滚)。


    family as water
    2009年9月30日 3:40
  • 我的意思是这样:
    数据库创建后 再由事务创建表 在创建表的时候 如果发生比如 停电、死机等情况(客户的电脑不稳定的有的是),因为表的创建还没有提交所以重启后就回滚了,而已经创建的数据库还在,这个怎么处理。

    看看 MS 在BOL 联机丛书 上的官方示例吧(注意:这不是我写的。不负责哟):

    USE master;

     GO

    IF DB_ID (N'mytest') IS NOT NULL

    DROP DATABASE mytest;

    GO

    CREATE DATABASE mytest;

    GO


    这就叫 害死人不赔命

    hello

    2009年9月30日 5:55
  • --查询数据库名称是否已经在使用
    Select @Data_Num = Count(*) From ( Select name From sys.databases ) as a Where a.name = @ObjectData_Name
    If @Data_Num > 0
            Begin
                    Set @Error_Text = '该数据库名称已使用,请修改后重试。'
                    GoTo RT1
            End

    我已经在创建数据库之前检查数据库是否存在了  我不会那么傻
    2009年9月30日 10:39
  • Anyway, don't think it's good practice to create database on the fly in sp.
    2009年9月30日 13:30