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 读取或 ...
随机推荐
- 单Js 的重力游戏开发
最近在用看cocos的时候萌生的想法,单纯js实现重力原理.然后就做了一个这样的小游戏.姑且命名为<超级玛丽>! 因为之前有人要我做超级玛丽.哈哈哈哈哈哈!这也算完成任务了吧. 先说一下原 ...
- CODEVS上一道很有趣的题(2145 判断奇偶性)
判断函数y=x^n次方的奇偶性若是奇函数就输出ji,偶函数输出ou 233333 用到了long long 还是爆了,于是就上了char a[1000000] =.= #include<stdi ...
- 查询表达式和LINQ to Objects
查询表达式实际上是由编译器“预处理”为“普通”的C#代码,接着以完全普通的方式进行编译.这种巧妙的发式将查询集合到了语言中,而无须把语义改得乱七八糟 LINQ的介绍 LINQ中的基础概念 降低两种数据 ...
- 蓝桥杯-兰顿蚂蚁-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...
- 利用PHPExcel读取Excel的数据和导出数据到Excel
PHPExcel是一个PHP类库,用来帮助我们简单.高效实现从Excel读取Excel的数据和导出数据到Excel.也是我们日常开发中,经常会遇到的使用场景.比如有个客户信息表,要批量导出发给同事,我 ...
- MFC六大关键技术
视频教程地址观看:http://pan.baidu.com/s/1mhKQ6kK 1.MFC六大关键技术sada)MFC程序的初始化过程:从CWinApp类派生一个应用程序类:使用派生类定义的全局变量 ...
- Linux增加磁盘操作
首先,增加磁盘分为4个大步骤:1.插上硬盘:2.分区;3.格式化4.挂载,然后分别说说以上四步的具体事项和注意内容. 1.插上硬盘(本位以虚拟机为例) 新买来一块磁盘,把磁盘插到主板上.虚拟机中操作如 ...
- servlet的过滤器的doFilter()
doFilter中的chain.doFilter(res,req);//Filter 只是链式处理,请求依然转发到目的地址 意思就说过滤器只是一个关口,如果符合条件的请求会被过滤器拦截下来,然后进行处 ...
- 【JavaScript OPP基础】---新手必备
今天和大家分享一下近期整理的有关JavaScriptOPP的基础知识~~~我们一起来学习一下-- JavaScriptOPP基础 一.面向对象编程OOP1.语言的分类:面向机器:汇编语言面向过程:C语 ...
- 让python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE等请求
这两天在用python的bottle框架开发后台管理系统,接口约定使用RESTful风格请求,前端使用jquery ajax与接口进行交互,使用POST与GET请求时都正常,而Request Meth ...