SQL SERVER 自动生成 MySQL 表结构及索引 的建表SQL

1 数据类型转换
- SQL SERVER中的datetime,保留到微秒(秒后小数点3位),而mysql仅保留到秒,转换后是否会影响业务,如果影响,需要新增一个字段专门来存储微秒或者毫秒,虽然mysql中没有时间数据类型的精度到达微秒或者毫秒,但是mysql提供对微秒的相关处理函数microsecond、extract跟date_format。
- MySQL使用tinyint代替SQL SERVER的bit
- SQL SERVER的money类型使用decimal替代
- timestamp的转换,SQL SERVER中是一个16进制的数字,代表时间戳,每次修改都会数值都会变大。
- 从功能考虑,转换为mysql的时候,处理为timestamp的数据类型,默认值为CURRENT_TIMESTAMP,行发生修改则定时修改这一列数据,如果这样转换,那么在SQL SERVER导入数据的时候,就要相应处理。(本文存储过程默认这么处理)
- 从数据考虑,转换为mysql的时候,处理为bigint的数据类型(修改存储过程case when b.name = 'timestamp' then ' timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ' 为case when b.name = 'timestamp' then ' bigint ' )
- 自增处理,mysql的自增步长跟增量值是整个实例统一的,不能每个表格动态修改,所以这里在转化的过程中,为auto_increment,根据实例的设置来处理
ID | SQL SERVER | MySQL | Description |
1 | bigint | bigint | |
2 | binary | binary | |
3 | bit | tinyint | SQL SERVER的bit类型,对于零,识别为False,非零值识别为True。 MySQL中没有指定的bool类型,一般都使用tinyint来代替 |
4 | char | char | |
5 | date | date | |
6 | datetime | datetime | 注意,mssql的保留到微秒(秒后小数点3位),而mysql仅保留到秒 |
7 | datetime2 | datetime | 注意,mssql的保留到微秒(秒后小数点7位),而mysql仅保留到秒 |
8 | datetimeoffset | datetime | 注意,mssql的保留时区,这个需要程序自己转换 mssql的保留到微秒(秒后小数点7位),而mysql仅保留到秒 |
9 | decimal | decimal | |
10 | float | float | |
11 | int | int | |
12 | money | float | 默认转换为decimal(19,4) |
13 | nchar | char | SQL SERVER转MySQL按正常字节数转就可以 |
14 | ntext | text | |
15 | numeric | decimal | |
16 | nvarchar | varchar | |
17 | real | float | |
18 | smalldatetime | datetime | |
19 | smallint | smallint | |
20 | smallmoney | float | 默认转换为decimal(10,4) |
21 | text | text | |
22 | time | time | 注意,mssql的保留到秒后小数点8位,而mysql仅保留到秒 |
23 | timestamp | timestamp | 注意,mssql的行时间戳,处理为mysql的 timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 。这会对后面导数据造成影响,从功能方面来看,可以按照上文转换;如果从数据来看,若需要转换16进制的文字存储到mysql中,则这里设置为bigint即可,在表格中的临时表中设置。 |
24 | tinyint | tinyint | |
25 | uniqueidentifier | varchar(40) | 对应mysql的UUID(),设置为文本类型即可。 |
26 | varbinary | varbinary | |
27 | varchar | varchar | |
28 | xml | text | mysql不支持xml,修改为text |
2 主键处理
- --SQL SERVER根据聚集索引的列情况来创建mysql的主键
- SELECT
- col_name(i.object_id,ik.column_id) pk_col
- FROM sys.indexes i
- JOIN sys.index_columns ik ON i.index_id=ik.index_id and i.object_id=ik.object_id
- WHERE i.type=1
- and i.object_id=object_id('tb')
- ORDER BY key_ordinal
3 索引添加
- MySQL不支持INCLUDE选项的包含索引,所以在处理的过程中,INCLUDE列添加到索引列中
- MySQL 不支持WHERE选项的过滤索引,所以在处理的过程中,WHERE选项去除
- 索引名字处理:包含列1-2个的,直接IX_表名,超过3个列的,取每列前3个字符,整个索引名长度不超过64个字符,超过截取前64个字符
4 测试

这里,尝试创建一个新表来测试。
- CREATE TABLE tbtest(
- id INT IDENTITY(1,1) NOT NULL ,
- name NVARCHAR(50) NOT NULL,
- phone VARCHAR(11) NOT NULL,
- age int default 99 ,
- birthday datetime default getdate(),
- addresss text,
- monyes money default 123456789012345.1234,
- smonyes smallmoney,
- nums int default 2,
- moneys money,
- smo smallmoney,
- curversion timestamp
- )
- ALTER TABLE tbtest ADD CONSTRAINT PK_tbtest PRIMARY KEY (ID,phone);
- CREATE INDEX IX_NAME ON tbtest(NAME);
- CREATE INDEX IX_phone_age ON tbtest(phone,age);
- CREATE INDEX IX_nums ON tbtest(nums) WHERE nums>2;
- CREATE INDEX IX_birthday ON tbtest(birthday) include (name,phone);
- exec p_tb_mssqltomysql 'tbtest'
- CREATE TABLE tbtest(id int not null auto_increment
- ,name varchar(50) not null
- ,phone varchar(11) not null
- ,age int null
- ,birthday datetime null
- ,addresss text null
- ,monyes decimal(19,4) null
- ,smonyes decimal(10,4) null
- ,nums int null
- ,moneys decimal(19,4) null
- ,smo decimal(10,4) null
- ,curversion timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP not null
- , primary key (id,phone) );
- CREATE INDEX IX_name ON tbtest( name );
- CREATE INDEX IX_phone_age ON tbtest( phone,age );
- CREATE INDEX IX_nums ON tbtest( nums );
- CREATE INDEX IX_bir_nam_pho ON tbtest( birthday,name,phone );

5 存储过程脚本
- -- =============================================
- -- Author: suxinyu
- -- Create date: 20170612
- -- Description: 根据表名自动把表格的所有建表DDL SQL转化为 MySQL的建表SQL,不包含分区表,不处理区域数据类型;执行过程中,需要把存储过程建立在需要导出的数据库中。
- -- Example: exec p_tb_mssqltomysql 'orders,ordernums,channels'
- -- =============================================
- --存储过程建立在需要导出表结构的DB上
- USE db
GO- CREATE PROC [dbo].[p_tb_mssqltomysql]
- @tbsql varchar(1000)
- AS
- SET NOCOUNT ON ;
- --处理tablename的字符串,把tablename字符串分割成每一行存储进入表变量中
- DECLARE @tab_tablename table(tbname varchar(100))
- DECLARE @tbname varchar(100)
- INSERT INTO @tab_tablename(tbname)
- SELECT
- SUBSTRING(@tbsql,NUMBER,CHARINDEX(',',@tbsql+',',NUMBER)-number)
- FROM master.dbo.spt_values
- WHERE TYPE='P' AND number>0 AND SUBSTRING(','+@tbsql,number,1)=','
- --把mysql跟mssql的数据类型对应起来存储
- --空间数据类型不处理
- --money类型处理为float
- --timestamp处理为 timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- DECLARE @tbtype table(mssql varchar(20),mysql varchar(20))
- INSERT INTO @tbtype(mssql,mysql) values( 'bigint','bigint'),('binary','binary'),('binary','binary'),('bit','tinyint'),('char','char'),('date','date'),('datetime','datetime'),('datetime2','datetime'),('datetimeoffset','datetime'),('decimal','decimal'),('float','float'),('int','int'),('money','decimal'),('nchar','char'),('ntext','text'),('numeric','decimal'),('nvarchar','varchar'),('real','float'),('smalldatetime','datetime'),('smallint','smallint'),('smallmoney','decimal'),('text','text'),('time','time'),('timestamp','timestamp'),('tinyint','tinyint'),('uniqueidentifier','varchar(40)'),('varbinary','varbinary'),('varchar','varchar'),('xml','text')
- DECLARE @tb_exec_sql table(tbname varchar(100),sql nvarchar(max),indexs nvarchar(max))
- DECLARE @indexs_sql nvarchar(max)
- --转化表格SQL
- DECLARE NAME CURSOR FOR
- SELECT tbname FROM @tab_tablename
- OPEN NAME
- FETCH NEXT FROM name INTO @tbname
- WHILE @@FETCH_STATUS =0
- BEGIN
- ;WITH data AS (
- SELECT
- case when b.is_unique=1 then ' UNIQUE ' else ' ' end is_unique,
- OBJECT_NAME(A.OBJECT_ID) obj_name,
- COL_NAME(A.object_id,A.column_id) colname,
- SUBSTRING(COL_NAME(A.object_id,A.column_id),1,3) col_short,
- is_included_column,
- index_column_id,
- a.index_id,
- A.OBJECT_ID
- FROM SYS.index_columns A INNER JOIN SYS.INDEXES B ON A.OBJECT_ID=B.OBJECT_ID AND A.index_id=B.index_id
- WHERE b.type!=1 and OBJECT_NAME(A.OBJECT_ID)=@tbname
- )
- SELECT
- @indexs_sql=
- REPLACE(
- (STUFF(
- (
- SELECT
- ' CREATE '
- + a.is_unique
- +' INDEX '
- + CASE WHEN COUNT(*) >=3 THEN SUBSTRING(('IX_'+stuff((SELECT '_'+col_short FROM data b where a.object_id=b.object_id and a.index_id=b.index_id FOR XML PATH('')),1,1,'')),1,64)
- ELSE 'IX_'+stuff((SELECT '_'+colname FROM data b where a.object_id=b.object_id and a.index_id=b.index_id FOR XML PATH('')),1,1,'')
- END
- +' ON '
- + a.obj_name
- +'( '
- + stuff((SELECT ','+colname FROM data b where a.object_id=b.object_id and a.index_id=b.index_id FOR XML PATH('')),1,1,'')
- +' );
- '
- FROM data a
- GROUP BY a.is_unique,a.obj_name,a.object_id,a.index_id
- ORDER BY a.object_id,a.index_id
- FOR XML PATH('')
- ),1,1,'')
- ),'
- ','')
- INSERT INTO @tb_exec_sql(tbname,indexs,sql)
- SELECT
- @tbname,@indexs_sql,
- 'CREATE TABLE '+@tbname+'('+
- REPLACE(
- STUFF( (
- SELECT
- ','+a.name
- +
- case when b.name = 'timestamp' then ' timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP '
- when b.name = 'uniqueidentifier' then ' varchar(40) '
- when b.name in ('char','nchar','nvarchar','varbinary','varchar') then ( case when a.length<0 then ' text ' else ' '+c.mysql+'('+ (case when b.name like 'n%' then cast(a.length/2 as varchar(10)) else cast(a.length as varchar(10)) end )+')' end )
- when b.name in ('decimal','float','money','numeric','smallmoney') then ' '+c.mysql+'('+ cast(a.prec as varchar(10)) +','+ cast(a.scale as varchar(10)) +') '
- else ' '+c.mysql+' ' end
- +
- case when a.isnullable=0 then ' not null ' else ' null ' end
- +
- case when COLUMNPROPERTY( A.ID,A.NAME,'ISIDENTITY')=1 then ' auto_increment ' else '' end
- +
- case when a.length<0 or b.name in ('text') then ' '
- when e.text like ' ((%' then ' default '+substring(e.text,3,len(e.text)-4)
- when e.text like ' (''%' then ' default '+substring(e.text,2,len(e.text)-2)
- else ' '
- end
- +
- ISNULL(' comment "'+cast(g.value as varchar(1000))+'"
- ','
- ')
- FROM sys.syscolumns A
- LEFT JOIN sys.systypes B ON A.XUSERTYPE=B.XUSERTYPE
- LEFT JOIN @tbtype C ON b.name collate Chinese_PRC_CI_AS = c.mssql
- LEFT JOIN sys.sysobjects D ON A.ID=D.ID AND D.XTYPE='U' AND D.NAME<>'DTPROPERTIES'
- LEFT JOIN sys.syscomments E ON A.CDEFAULT=E.ID
- LEFT JOIN sys.extended_properties G ON A.ID=G.major_id AND A.COLID=G.minor_id
- WHERE D.NAME =@tbname
- order by a.colid
- FOR XML PATH('')
- ),1,1,'')
- ,'
- ','')
- +
- ISNULL(
- ( SELECT
- ', primary key ('+STUFF(
- (
- SELECT
- ','+col_name(i.object_id,ik.column_id)
- FROM sys.indexes i
- JOIN sys.index_columns ik ON i.index_id=ik.index_id and i.object_id=ik.object_id
- WHERE i.type=1 and i.object_id=object_id(@tbname)
- ORDER BY key_ordinal
- FOR XML PATH('')
- ),1,1,'')
- +') '
- )
- ,'')
- +
- ')'
- +
- ISNULL( (
- SELECT
- ' COMMENT "'+CAST(value AS VARCHAR(1000))+'";
- '
- FROM sys.extended_properties
- where major_id=object_id(@tbname) and minor_id=0
- ),';')
- FETCH NEXT FROM NAME INTO @tbname
- END
- CLOSE NAME
- DEALLOCATE NAME
- SELECT * FROM @tb_exec_sql
SQL SERVER 自动生成 MySQL 表结构及索引 的建表SQL的更多相关文章
- Entity Framewrok 7beta7中不同版本sql server自动生成分页sql语句的问题
在EF中,使用linq进行分页是很方便的,假如我们有一个EMP表,结构如下: public class Emp { [Key] public Guid No { get; set; } public ...
- 【SQL】用Sql Server自动生产html格式的数据字典
原文:[SQL]用Sql Server自动生产html格式的数据字典 本文软件环境:Sql Server 2008. 1.打开sql server管理器,给选定的表添加描述信息,给指定的字段添加描述信 ...
- SQL Server 动态生成数据库所有表Insert语句
一. 背景 SQL Server,如果我们需要把数据库A的所有表数据到数据库B中,通常我们会怎么做呢?我会使用SSMS的导入导出功能,进行表数据的导入导出,无可厚非,这样的导入非常简单和方便: 但是, ...
- (转)如何将数据库从SQL Server迁移到MySQL
一.迁移Database Schema. 首 先使用Sybase Powerdesigner的逆向工程功能,逆向出SQL Server数据库的物理模型.具体操作是在Powerdesigner中选择“F ...
- [PowerDesign]将数据库从SQL Server数据库转换为MySQL
原文:[PowerDesign]将数据库从SQL Server数据库转换为MySQL 一.迁移Database Schema. 首先使用Sybase Powerdesigner的逆向工程功能,逆向出S ...
- 如何在SQL Server中生成和使用CRUD存储过程
在本文中,请参阅如何在SQL Server中生成和使用CRUD存储过程. 大多数数据库系统基于缩写CRUD调用的最简单的4种数据操作操作进行操作. 此首字母缩写词代表CREATE,READ,UPDAT ...
- 通过SQL Server 2008 访问MySQL(转)
在公司中经常会遇到部署多种数据库环境的情况,对于开发人员来说经常在不同数据库之间转换确实有些繁琐,本篇将介绍从SQL Server 操作MySQL 数据库的方法. 数据库测试环境 1. SQL Ser ...
- SQL Server :理解数据记录结构
原文:SQL Server :理解数据记录结构 在SQL Server :理解数据页结构我们提到每条记录都有7 bytes的系统行开销,那这个7 bytes行开销到底是一个什么样的结构,我们一起来看下 ...
- SQL Server :理解数据页结构
原文:SQL Server :理解数据页结构 我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或 ...
随机推荐
- Python之路- 反射&定制自己的数据类型
一.isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 issubclass(sub, super)检查sub类是否是 super ...
- [ SharePoint ADFS 开发部署系列 (一)]
前言 本文完全原创,转载请说明出处,希望对大家有用. 随着企业信息化建设逐渐成熟,基于微软体系的企业内部系统架构在众多企业中得到应用,随之而来的用户统一身份认证(SSO)问题成为企业IT部门急需解决的 ...
- 简谈-Python一些常用的爬虫技巧
第一种:基本的网页抓取 get方法 import urllib2url = "链接response = urllib2.urlopen(url)print response.read() p ...
- python练习_12
题目:敏感词文本文件 filtered_words.txt,里面的内容 和 0011题一样,当用户输入敏感词语,则用 星号 * 替换,例如当用户输入「北京是个好城市」,则变成「**是个好城市」.(11 ...
- 纯HTML课表
table标签构造课表 table标签常用于制作表格以及简单布局,于是我就玩了下table标签,用table标签也能构造出很漂亮的页面呢,虽然在博客页面加入与实际打开页面稍微有点出入,但还是可以接受的 ...
- android在myeclipse上创建的项目各种报错
这几天被android弄得头疼死了.差不多把电脑弄了个遍. 先是离线安装ADT,下载ADT,然后配置,但是因为ADT与MyEclipse冲突.所以直接不要再myeclipse下弄Android的环境了 ...
- Laravel5中Cookie的使用
今天在Laravel框架中使用Cookie的时候,碰到了点问题,自己被迷糊折腾了半多小时.期间研究了Cookie的实现类,也在网站找了许多的资料,包括问答.发现并没有解决问题.网上的答案都是互相抄袭, ...
- WPF 自定义ColorDialog DropDownCustomColorPicker
今天分享一个 WPF 版的ColorDialog,该控件源自 这里,不过笔者已经该控件做了大量的修改工作,以适应自己的产品需求,闲话少说,先看看效果图: 1.DropDownCustomColorPi ...
- fgets()函数以及fputs()函数
fgets() fgets() 该函数是一个文件操作相关的函数 暂时使用这个函数可以从键盘接收一个字符串,保存到字符数组中 原来接收字符串保存到数组中的方法: char str[50]; 1) sca ...
- percona-xtrabackup安装
二进制包安装(推荐安装方式,不用安装依赖包,非常方便): 1.下载安二进制包: wget https://www.percona.com/downloads/XtraBackup/Perco ...