【问题标题】:Converting MySQL DDL to SQL Server DDL将 MySQL DDL 转换为 SQL Server DDL
【发布时间】:2010-07-21 05:52:19
【问题描述】:

我有一个为 MySQL 5 生成的模型,但现在我需要在 SQL Server 安装上创建这些表。

我已经搞砸了 SQL Server,我想确保我可以将此脚本转换为兼容。

我真的不知道要寻找什么 TBQH,所以事不宜迟,这是我的 MySQL DDL

CREATE SCHEMA IF NOT EXISTS `bof_survey` DEFAULT CHARACTER SET utf8 COLLATE default collation ;
USE `bof_survey`;

-- -----------------------------------------------------
-- Table `bof_survey`.`question`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `bof_survey`.`question` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `text` VARCHAR(255) NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `bof_survey`.`category`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `bof_survey`.`category` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NOT NULL ,
  `adverb` VARCHAR(45) NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `bof_survey`.`answer`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `bof_survey`.`answer` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `question_id` INT UNSIGNED NULL ,
  `category_id` INT UNSIGNED NULL ,
  `text` VARCHAR(60) NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_answer_question` (`question_id` ASC) ,
  INDEX `fk_answer_category1` (`category_id` ASC) ,
  CONSTRAINT `fk_answer_question`
    FOREIGN KEY (`question_id` )
    REFERENCES `bof_survey`.`question` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_answer_category1`
    FOREIGN KEY (`category_id` )
    REFERENCES `bof_survey`.`category` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

【问题讨论】:

    标签: mysql sql-server ddl


    【解决方案1】:

    开始的一种方法是将 DDL 加载到 MySQL 数据库中,然后使用 mysqldump --compatible=mssql 重新转储它。这应该让您开始 - 从那里开始可能会通过 T-SQL 文档并在此逐案询问。

    此外,Microsoft 有一些资源,例如this article(适用于 SQL Server 2000,但它可以帮助正确映射数据类型)。

    【讨论】:

    • 我尝试在自己的转换中使用 mysqldump,但它并没有真正帮助。我认为它可能会翻译一些数据类型,但事实并非如此。此外,它以错误的顺序转储表,不允许定义外键。 (但是,它确实成功地注释掉了所有 MySQL SET 命令 :-) YMMV。我有原始的 MySQL DDL 脚本,就我而言,我发现手动转换它更容易,在 SQL Server Mgmt Studio 的 sql 编辑器中打开脚本并解决它突出显示的问题。
    【解决方案2】:

    彼得,

    这里需要考虑 MySQL 和 MSSQL 之间的一些差异,尤其是模式。我不太清楚它们是如何与 MySQL 一起工作的,但它似乎几乎就像 MSSQL 所称的数据库一样。

    MSSQL 中的架构更像是一个安全抽象层,用于对数据库内的对象进行分组。这是 AFAIK 没有大量使用的东西,但 MS 想要推广的东西。我把它放在这里了,然后在默认模式(通常是 dbo)中创建对象。

    不用说,其余的都很简单:

    -- ----------------------------------------------------- 
    -- Table question
    -- ----------------------------------------------------- 
    IF NOT EXISTS ( SELECT  *
                    FROM    sys.objects
                    WHERE   name = 'question' ) 
        BEGIN
            CREATE  TABLE question
                (id int IDENTITY(1, 1)
                        NOT NULL,
                 text varchar(255) NOT NULL,
                 PRIMARY KEY (id)) ; 
        END 
    
    -- ----------------------------------------------------- 
    -- Table category 
    -- ----------------------------------------------------- 
    IF NOT EXISTS ( SELECT  *
                    FROM    sys.objects
                    WHERE   name = 'category' ) 
        CREATE  TABLE category
            (id int IDENTITY(1, 1)
                    NOT NULL,
             name varchar(45) NOT NULL,
             adverb varchar(45) NOT NULL,
             PRIMARY KEY (Id)) ; 
    
    -- ----------------------------------------------------- 
    -- Table answer 
    -- ----------------------------------------------------- 
    IF NOT EXISTS ( SELECT  *
                    FROM    sys.objects
                    WHERE   name = 'answer' ) 
        CREATE  TABLE answer
            (id int IDENTITY(1, 1)
                    NOT NULL,
             question_id int NULL,
             category_id int NULL,
             text varchar(60) NULL PRIMARY KEY (Id),
             CONSTRAINT fk_answer_question FOREIGN KEY (question_id) REFERENCES question (id) ON DELETE NO ACTION ON UPDATE NO ACTION,
             CONSTRAINT fk_answer_category1 FOREIGN KEY (category_id) REFERENCES category (id) ON DELETE NO ACTION ON UPDATE NO ACTION);
    
    CREATE INDEX fk_answer_question ON answer(question_id ASC) 
    CREATE INDEX fk_answer_category1 ON answer(category_id ASC) 
    

    请注意以下变化:

    • AUTO_INCREMENT 已交换 身份。您指定起始值和增量
    • MSSQL 没有 SIGNED 或 UNSIGNED 整数的概念
    • 默认情况下,主键将创建为聚集索引
    • 除非指定,否则索引将被创建为非唯一且非聚集的

    列名“文本”是保留关键字,也应该更改,以停止任何解析问题。

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      另一种可能性(如果您可以访问 MySQL 数据库本身,而不是 DDL)是使用 Microsoft 发布的迁移向导:

      对于迁移到 SQL Server 2008:http://www.microsoft.com/downloads/details.aspx?FamilyID=0e6168b0-2d0c-4076-96c2-60bd25294a8e&displaylang=en

      对于迁移到 SQL Server 2005:http://www.microsoft.com/downloads/details.aspx?FamilyID=c6f14640-da22-4604-aaaa-a45de4a0cd4a&displaylang=en

      我已经使用了 SQL Server 2008 的向导...效果很好。

      -布赖恩

      【讨论】:

        【解决方案4】:

        我正在将 DDL 从 MySQL Server 版本 5.7.12 导出到 SQL Server 版本 12.00.6024 并发现以下内容:

        1. 当我从 MySQL 导出 DDL 时,列名用反引号括起来,例如`my_column_name` 但是当我从 SQL Server 导出时,列名被括号 [my_column_name] 包围。

        我解决了这个问题,首先对所有反引号进行文本搜索并将它们替换为左括号 ([),然后在左括号后跟空格 ([) 进行搜索,然后将它们替换为右括号后跟 a空格 (] ),然后在左括号后跟逗号 ([,) 进行搜索,并将它们替换为右括号后跟逗号 (],) 等等。

        1. MySQL 使用关键字KEY 表示INDEX。由于还识别出了实际的PRIMARY KEYFOREIGN KEY,我不得不手动遍历脚本并替换。

        2. MySQL 导出的列类型为 bigint(20)。我把这些改成了bigint

        3. 我把CHARACTER SET latin1改成了COLLATE latin1

        4. 我把double改成了float(53)

        5. 我删除了UNIQUE KEY [NAME] ([NAME]),,并在创建表ALTER TABLE [my_table] ADD CONSTRAINT UNQ_NAME UNIQUE([NAME])之后创建了一条alter语句。

        【讨论】:

          【解决方案5】:

          两次导出所有表定义后,我放弃了,只是用Python编写了代码。

          count = 0
          unique_keys = []
          with open(my_sql_file_path, 'r') as input_file:
              data = input_file.readlines()
          
          for line in data:
              count = count + 1
              if '`;' in line:
                  line = line.replace('`;', '];')
              if '`,' in line:
                  line = line.replace('`,', '],')
              if '` ' in line:
                  line = line.replace('` ', '] ')
              if '`)' in line:
                  line = line.replace('`)', '])')
              if '`\n' in line:
                  line = line.replace('`\n', ']\n')
              if '`' in line:
                  line = line.replace('`', '[')
              if 'ENGINE' in line.upper():
                  line = line.replace('ENGINE', '-- ENGINE')
              if 'DOUBLE' in line.upper():
                  line = line.replace('double', 'float(53)')
                  line = line.replace('DOUBLE', 'FLOAT(53)')
              if 'ENGINE' in line.upper():
                  line = line.replace('ENGINE', '-- ENGINE')
                  line = line.replace('engine', '-- ENGINE')
              if 'bigint(20)' in line:
                  line = line.replace('bigint(20)', 'bigint')
              if 'bigint(15)' in line:
                  line = line.replace('bigint(15)', 'bigint')
              if 'CHARACTER SET' in line:
                  line = line.replace('CHARACTER SET', 'COLLATE')
              if 'KEY' in line:
                  if 'PRIMARY KEY' not in line \
                          and 'UNIQUE KEY' not in line\
                          and '_KEY_' not in line:
                      line = line.replace('KEY', 'INDEX')
                  if 'UNIQUE KEY' in line:
                      row_num = (str(count) + " ")
                      unique_keys.append(row_num)
                  print(line)
          print("Manually change these UNIQUE KEY lines to ALTER TABLE statements", unique_keys)
          

          【讨论】: