澳门贵宾会注册送豪礼基于Python的SQL Server数据库实现对象同步轻量级

缘由

数据库概述 / Database Overview


 

1 关于SQL /
About SQL

构化查询语言(Structured
Query
Language卡塔尔(قطر‎简单称谓SQL,是一种极度指标的编制程序语言,是一种数据库查询和顺序设计语言,用于存取数据以至询问、更新和保管关周详据库系统;同一时间也是数据库脚本文件的扩大名。

结构化查询语言是尖端的非进度化编制程序语言,允许客户在高层数据结构上干活。它不必要客户钦点对数据的贮存方法,也没有必要顾客掌握实际的多少寄放格局,所以具备完全两样底层布局的两样数据库系统,
能够使用相仿的构造化查询语言作为数据输入与治本的接口。构造化查询语言语句能够嵌套,那使它富有非常的大的油滑和强有力的成效。

1.1 SQL语言 /
SQL Language

布局化查询语言包罗6个部分:

1.
多少查询语言(DQL: Data Query Language

其语句,也称为“数据检索语句”,用以从表中获得数据,分明数据怎么样在应用程序给出。保留字SELECTDQL(也是享有SQL)用得最多的动词,其余DQL常用的保留字有WHERE,O昂CoraDER
BY,GROUP
BY和HAVING。那个DQL保留字常与别的品种的SQL语句一起利用。

2.
数量操作语言(DML: Data Manipulation Language

其语句包蕴动词INSERT,
UPDATEDELETE。它们各自用于增添,改进和删除表中的行。也可以称作动作查询语言。

3.
事务管理语言(TPL

它的口舌能作保被DML语句影响的表的具有行随时得以更新。TPL语句富含BEGIN
TRANSACTION,COMMIT和ROLLBACK。

4.
数目调控语言(DCL

它的说话通过GRANTREVOKE收获批准,明确单个客户和客户组对数据库对象的探问。某个GL450DBMS可用GRANT或REVOKE调节对表单个列的拜候。

5.
多少定义语言(DDL

其语句满含动词CREATEDROP。在数据库中创建新表或删除表(CREAT
TABLE 或 DROP
TABLE);为表参预索引等。DDL包涵不菲与食指据库目录中取得数量有关的保留字。它也是动作查询的一有的。

6.
指针调控语言(CCL

它的说话,像DECLARE
CURSOR
, FETCH INTOUPDATE WHERE
CURRENT
用以对三个或多少个表单独行的操作

 

1.2 SQL数据类型
/ SQL Data

构造化查询语言共有三种数据类型,字符型文本型数值型逻辑型日期型

1. 字符型

**VARCHAR VS
CHAR**

VARCHA景逸SUV型和CHA福特Explorer型数据的这几个差别是微微的,可是那么些首要。他们都以用来存储字符串长度小于255的字符。

要是你向三个尺寸为叁贰拾个字符的VARCHAR型字段中输入数据BillGates。当你现在从那几个字段中抽出此数量时,你收取的数码其尺寸为十一个字符——字符串BillGates的长短。假设你把字符串输入一个长度为肆拾个字符的CHAR型字段中,那么当你抽取数据时,所抽取的多寡长度将是肆十个字符。字符串的末端会被增好多余的空格

当你创立和煦的站点时,你会意识采取VARCHAMurano型字段要比CHATiggo型字段方便的多。使用VARCHA福特Explorer型字段时,你无需为剪掉你多少中多余的空格而悲观。

VARCHAEnclave型字段的另一个凸起的收益是它能够比CHA冠道型字段占用越来越少的内部存款和储蓄器和硬盘空间。当你的数据库非常的大时,这种内部存款和储蓄器和磁盘空间的节约会变得异常主要。

2. 文本型
TEXT

使用文本型数据,你能够存放抢先七十亿个字符的字符串。当您供给存款和储蓄大串的字符时,应该利用文本型数据。

当心文本型数据尚无长度,而上一节中所讲的字符型数据是有长度的。多少个文本型字段中的数据平日照旧为空,要么非常的大。

当您从HTML
FORM的多行文本编辑框(TEXTAREA)中募集数据时,你应有把访问的消息囤积于文本型字段中。可是,无论哪一天,假如您能幸免选取文本型字段,你就应当不使用它。文本型字段既大且慢,滥用文本型字段会使服务器速度变慢。文本型字段还可能会吃掉大批量的磁盘空间

举例您向文本型字段中输入了别的数据(以至是空值),就能够有2K的空间被活动分配给该数量。除非删除该记录,不然你不恐怕收回那某个囤积空间。

3. 数值型 整数INT
小数NUMERIC 钱数MONEY

INT VS SMALLINT VS
TINYINT

通常,为了省去空间,应该尽大概的运用最小的整型数据。一个TINYINT型数码只占用多少个字节;一个INT型数码占用七个字节。那看起来就好像差异相当小,可是在可比大的表中,字节数的增高是全速的。另一面,一旦你已经创办了五个字段,要改良它是十分不方便的。因而,为安全起见,你应有预测一下,一个字段所急需仓库储存的数值最大有非常大大概是多大,然后选用适当的数据类型。

NUMERIC

为了能对字段所存放的数目有越来越多的主宰,你能够使用NUME逍客IC型数据来还要表示二个数的寸尾部分和小数部分。NUME奥迪Q5IC型数据使您能表示超大的数——比INT型数据要大得多。三个NUME奔驰G级IC型字段能够积累从-10^38到10^38界定内的数。NUMEXC60IC型数据还使您能代表有小数部分的数。比如,你能够在NUME奥迪Q5IC型字段中积攒小数3.14。

MONEY VS
SMALLMONEY

您能够使用
INT型或NUMECRUISERIC型数据来囤积钱数。不过,特意有其它几种数据类型用于此目标。

若是你希望您的网点能挣超多钱,你能够动用MONEY型数码。假如你的野心相当的小,你能够应用SMALLMONEY型数码。MONEY型数据能够储存从-922,337,203,685,477.5808922,337,203,685,477.5807的钱数。假诺你要求仓库储存比那还大的金额,你能够利用NUMERIC型数据。

SMALLMONEY型数码只可以存款和储蓄从-214,748.3648214,748.3647
的钱数。相通,假使得以的话,你应当用SMALLMONEY型来顶替MONEY型数据,以节约空间

4. 逻辑型
BIT

假诺你利用复选框(CHECKBOX)从网页中收载新闻,你能够把此音信存款和储蓄在BIT型字段中。BIT型字段只可以取七个值:0或1

Note:
在您创制好八个表之后,无法向表中增添
BIT型字段。假若你希图在贰个表中满含BIT型字段,你必须要在创制表时达成

5. 日期型

DATETIME VS
SMALLDATETIME

一个DATETIME型的字段能够积累的日期范围是从1753年7月1日首先纳秒到9999年三月一日最终一纳秒

一旦你没有必要覆盖这么大规模的日子和岁月,你能够行使SMALLDATETIME型数码。它与DATETIME型数据一致利用,只不过它能表示的日期和岁月节制比DATETIME型数据小,何况不比DATETIME型数据正确。两个SMALLDATETIME型的字段能够存款和储蓄从一九〇五年1月1日到2079年7月6日的日期,它只好准确到

DATETIME型字段在你输入日期和时间此前不包罗实际的数据,认知那或多或少是最重要的

 

1.3 SQL常用命令
/ SQL Frequent Command

      
可参考常用命令。

1.4 T-SQL简介澳门贵宾会注册送豪礼, /
About Transact-SQL

Transact-SQL(T-SQL卡塔尔是微软绵绵Sybase使用的一种SQL扩充语言,用于与关系型数据库举办作业交互作用。T-SQL扩充了SQL的多项专门的学业,包含经过编制程序,当地变量及各类辅助函数,同有时间也对DELETE和UPDATE语句进行了改换,允许DELETE与UPDATE扩张条件FROM。

在流水生产线调整方面,参与了BEGIN和END,BREAK,CONTINUE,GOTO甚至IF和ELSE,RETUWranglerN,WAITFO大切诺基和WHILE等,使其更具编制程序化。

 

2 至于数据库
/ About Database

2.1
常用数据库

前段时间主要的二种流行数据库为MySQL,
SQL server, Oracle, Sysbase,
Access等,详细内容可以参考常用数据库。

2.1.1 MySQL

2.1.1.1
MySQL简介

MySQL是最受招待的开源SQL数据库处理体系,它由MySQL
AB开拓、发表和支撑。MySQL AB是一家基于MySQL开荒职员的商业铺面

MySQL是一个即刻的、八线程、多顾客和硬朗的SQL数据库服务器。MySQL服务器扶持至关心注重要任务、重负载临蓐系统的行使,也足以将它放到到一个大布局(mass-
deployed卡塔尔国的软件中去。

  与别的数据库管理种类相比较,MySQL具备以下优势:

  (1)MySQL是贰个关周详据库处理种类。

  (2)
MySQL是开源的。

  (3卡塔尔(قطر‎MySQL服务器是叁个快速的、可信赖的和易于使用的数据库服务器。

  (4卡塔尔MySQL服务器职业在客户/服务器嵌入系统中。

  (5卡塔尔国有恢宏的MySQL软件能够运用

2.1.1.2
MySQL使用教程

有关MySQL数据库的施用能够参谋教程。

2.1.1.3
MySQL数据类型

能够参见MySQL的数据类型。

2.1.1.3.1
整型

MySQL数据类型

含义(有符号)

tinyint(m)

1个字节  范围(-128~127)

smallint(m)

2个字节  范围(-32768~32767)

mediumint(m)

3个字节  范围(-8388608~8388607)

int(m)

4个字节  范围(-2147483648~2147483647)

bigint(m)

8个字节  范围(+-9.22*10的18次方)

Note:
取值范围假使加了unsigned,则最大值翻倍,如tinyint
unsigned的取值范围为(0~256卡塔尔(قطر‎。
int(mState of Qatar里的m是表示SELECT查询结果集中的呈现上升的幅度,并不影响其实的取值范围,未有影响到展现的增加率,不通晓那几个m有何用。

2.1.1.3.2
浮点型(float和double)

MySQL数据类型

含义

float(m,d)

单精度浮点型,8位精度(4字节),m总个数,d小数位

double(m,d)

双精度浮点型,16位精度(8字节),m总个数,d小数位

Note:
设一个字段定义为float(5,3卡塔尔国,假若插入四个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位。

2.1.1.3.3
定点数

浮点型在数据库中寄存的是近乎值,而牢固类型在数据库中存放的是正确值。

decimal(m,d)参数m<65 是总个数,d<30且 d<m 是小数位。

2.1.1.3.4
字符串(char, varchar, _text)

MySQL数据类型

含义

char(n)

固定长度,最多255个字符

varchar(n)

固定长度,最多65535个字符

tinytext

可变长度,最多255个字符

text

可变长度,最多65535个字符

mediumtext

可变长度,最多2的24次方-1个字符

longtext

可变长度,最多2的32次方-1个字符

charvarchar

1.char(n)若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉。所以char类型存款和储蓄的字符串末尾不能够有空格,varchar不限于此。

2.char(n卡塔尔(قطر‎固定长度,char(4卡塔尔不管是存入几个字符,都将占领4个字节,varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255卡塔尔,所以varchar(4卡塔尔国,存入3个字符将侵占4个字节。

3.char类型的字符串检索速度要比varchar类型的快。

varchartext

1.varchar可钦定n,text不能够钦定,内部存储varchar是存入的其实字符数+1个字节(n<=255)或2个字节(n>255卡塔尔国,text是实在字符数+2个字节。

2.text类型不能有默许值。

3.varchar可一直成立索引,text创立索引要钦命前有个别个字符。varchar查询速度快于text,在都创造索引的状态下,text的目录就像不起功效。

2.1.1.3.5
二进制数据(_Blob)

1._BLOB和_text存款和储蓄格局各异,_TEXT以文件情势存款和储蓄,立陶宛语存款和储蓄区分朗朗上口写,而_Blob是以二进制方式存款和储蓄,不分大小写。

2._BLOB存款和储蓄的数据只好完全读出。

3._TEXT能够钦命字符集,_BLO不用钦赐字符集。

2.1.1.3.6
日期时间等级次序

MySQL数据类型

含义

date

日期 ‘2008-12-2’

time

时间 ’12:25:36′

datetime

日期时间 ‘2008-12-2 22:06:44’

timestamp

自动存储记录修改时间

若定义八个字段为timestamp,那一个字段里的小运数额会随其余字段改革的时候自动刷新,所以这些数据类型的字段可以存放那条记下最终被改变的岁月。

2.1.1.3.7
数据类型的品质

 MySQL关键字

含义

NULL  

数据列可包含NULL值

NOT   NULL

数据列不允许包含NULL值

DEFAULT  

默认值

PRIMARY   KEY

主键

AUTO_INCREMENT  

自动递增,适用于整数类型

UNSIGNED  

无符号

CHARACTER   SET name

指定一个字符集

 

2.1.1.4
MySQL自带数据库

2.1.1.4.1
information_schema

MySQL中,除了活动安装的数据库外,还会有四个information_schema数据库,详细新闻来源于仿照效法链接。

information_schema数据库是MySQL自带的,它提供了访谈数据库元数据的主意。什么是元数据吧?元数据至于数据的数额,如数据库名或表名,列的数据类型,或访问权限等。有个别时候用于表述该消息的此外术语包含“数据辞典”和“系统目录”。


MySQL中,把information_schema看作是三个数据库,确切说是消息数据库。其中保存着至于MySQL服务器所维护的富有其余数据库的音信。如数据库名,数据库的表,表栏的数据类型与拜望权限等。在information_schema中,有数个只读表。它们其实是视图,实际不是基本表,因而,你将不可能看见与之血肉相连的别样公文。

2.1.1.4.1.1
数据库内的表表明

SCHEMATA表:
提供了这两天mysql实例中装有数据库的音信show
databases
的结果取之此表。

TABLES表:
提供了有关数据库中的表的音信(富含视图)。详细表述了有个别表归于哪个schema,表类型,表引擎,制造时间等新闻。show
tables from schemaname
的结果取之此表。

COLUMNS表:
提供了表中的列消息。详细表述了某张表的具备列以至各类列的音讯。show
columns from schemaname.tablename
的结果取之此表。

STATISTICS表:
提供了有关表索引的新闻。show index from
schemaname.tablename
的结果取之此表。

USER_PRIVILEGES(客户权限卡塔尔国表:
给出了有关全程权限的新闻,该音讯源自于mysql.user授权表。是非规范表

SCHEMA_PRIVILEGES(方案权限)表:
给出了有关方案(数据库)权限的新闻。该新闻来源mysql.db授权表。是非标准表

TABLE_PRIVILEGES(表权限)表:
给出了有关表权限的消息。该音讯源自mysql.tables_priv授权表。是非规范表

COLUMN_PRIVILEGES(列权限)表:
给出了关于列权限的消息。该音讯源自mysql.columns_priv授权表。是非标准表

CHARACTER_SETS(字符集)表:
提供了mysql实例可用字符集的音讯。show character
set
的结果集取之此表。

COLLATIONS表:
提供了有关各字符集的争执统一消息。

COLLATION_CHARACTER_SET_APPLICABILITY表:
指明了可用来校对的字符集。这几个列等效于show
collation
的前四个展现字段。

TABLE_CONSTRAINTS表:
描述了设有限定的表。以至表的牢笼类型。

KEY_COLUMN_USAGE表:
描述了具有约束的键列。

ROUTINES表:
提供了有关存款和储蓄子程序(存款和储蓄程序和函数)的新闻。此时,ROUTINES表不含有自定义函数(UDF)。名叫“mysql.proc
name”的列指明了对应于INFORMATION_SCHEMA.ROUTINES表的mysql.proc表列。

VIEWS表:
给出了关于数据库中的视图的音信。需求有show
views权限,不然无法查看视图消息。

TRIGGERS表:
提供了关于触发程序的音信。必需有super权限技术查看该表。

2.1.1.4.1.2
接纳技艺

  1. 类似MS SQL
    SERVER中的SP_HELPTEXT翻开存款和储蓄进程、函数、视图的功能

SHOW CREATE PROCEDURE
存款和储蓄进度名;

SHOW CREATE FUNCTION
函数名;

SHOW CREATE VIEW
视图名;

还能接纳以下格局(但下边包车型大巴办法只包蕴存款和储蓄进度主体部分,不带有Create以致传入参数注明的一对):

SELECT
ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES WHERE
ROUTINE_SCHEMA=’数据库名’ AND ROUTINE_TYPE=’PROCEDURE’ and
ROUTINE_NAME=’存款和储蓄进度名’;

函数也相通,只必要将查询条件对应改成ROUTINE_TYPE=’FUNCTION’就行

2.
查看脚下实例包含的数据库列表

SELECT * FROM
INFORMATION_SCHEMA.SCHEMATA;

3.
查询数据库中享有的表(包含视图

SELECT * FROM
INFORMATION_SCHEMA.tables WHERE TABLE_SCHEMA=’数据库名’ and
TABLE_TYPE=’BASE TABLE’;

SELECT * FROM
INFORMATION_SCHEMA.tables WHERE TABLE_SCHEMA=’数据库名’ and
TABLE_TYPE=’VIEW’;

4.
查询数据库中具有的视图

SELECT * FROM
INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA=’数据库名’;

5.
查询表对应的字段

a. SELECT * FROM
INFORMATION_SCHEMA.COLUMNS WHERE table_schema=’数据库名’ and
table_name=’表名’;

b.
横向列出表对应的字段,方便写Insert语句: select
GROUP_CONCAT(COLUMN_name) as ‘字段’ from INFORMATION_SCHEMA.COLUMNS
WHERE table_schema=’数据库名’ and table_name=’表名’;

6.
询问关键字在什么样存款和储蓄进程只怕函数中设有

SELECT * FROM
INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA=’数据库名’ AND
ROUTINE_TYPE=’PROCEDURE’ AND ROUTINE_DEFINITION like
‘%关键字%’;

SELECT * FROM
INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA=’数据库名’ AND
ROUTINE_TYPE=’FUNCTION’ AND ROUTINE_DEFINITION like ‘%关键字%’;

2.1.2 SQL
Server

2.1.2.1 SQL
Server简介

SQL Server
(MSSQL)是由微软开辟的数据库管理种类,是Web上最盛行的用于存款和储蓄数据的数据库,它已普及用于电商、银行、保证、电力等与数据库有关的本行。

时下最新版本是SQL
Server
2006,它只好在Windows上运转,操作系统的系统牢固对数据库拾分要害。并行施行和现存模型并不成熟,很难管理日益增加的顾客数和数据卷,伸缩性有限。

SQL Server
提供了大多的Web和电子商务功效,如对XML和Internet标准的丰硕援救,通过Web对数码进行轻便安全的拜访,具有强有力的、灵活的、基于Web的和日喀则的应用程序管理等。何况,由于其易操作性及其友好的操作分界面,非常受相近客商的挚爱。

 

2.1.3
Oracle

聊起数据库,第一个想到的厂商,日常都会是Oracle(陶文卡塔尔。该商厦树立于1976年,最先是一家专门开采数据库的商店。Oracle在数据库领域直接处在超过地位。
1981年,首先将关周密据库转到了桌面电脑上。然后,Oracle5率先推出了遍及式数据库、顾客/服务器结构等崭新的定义。Oracle
6首创行锁定方式以至对称多处理计算机的支撑,最新的Oracle
8首要扩展了对象技巧,成为涉及—对象数据库系统。前段时间,Oracle产物覆盖了大、中、小型Computer等几十种机型,Oracle数据库成为世界上利用最见惯不惊的关全面据系统之一。

Oracle数据库付加物全体以下能够脾气。

(1卡塔尔国 包容性:
Oracle成品使用标准SQL,并由此United States国标手艺所(NISTState of Qatar测验。与IBM
SQL/DS、DB2、INGRES、IDMS/猎豹CS6等卓越。

(2State of Qatar 可移植性:
Oracle的出品可运转于很宽范围的硬件与操作系统平台上。能够设置在70种以上区别的大、中、小型计算机上;可在VMS、DOS、UNIX、Windows等四种操作系统下办事。

(3卡塔尔(قطر‎ 可联结性:
Oracle能与多样通信网络不断,支撑各样协商(TCP/IP、DECnet、LU6.2等)。

(4卡塔尔 高分娩率:
Oracle产物提供了各样开拓工具,能小幅地点便顾客张开越来越付出。

(5State of Qatar 开放性:
Oracle优质的宽容性、可移植性、可连接性和高生产率使Oracle
奥迪Q3DBMS具有特出的开放性。

2.1.4
Sysbase

一九八一年,马克 B.
Hiffman和罗BertEpstern创立了Sybase公司,并在一九八七年临蓐了Sybase数据库付加物。Sybase主要有二种版本:一是UNIX操作系统下运营的版本;二是Novell
Netware情况下运作的本子;三是Windows
NT际遇下运营的版本。对UNIX操作系统,近期选拔最清汤寡水的是SYBASE 10及SYABSE
11 for SCO UNIX。

Sybase数据库的表征:

(1卡塔尔(قطر‎它是依照客户/服务器系统构造的数据库。

(2)它是当真开放的数据库。

(3卡塔尔它是一种高质量的数据库。

2.2
数据库构造

2.2.1 数据库
/ Database

Visual
Basic中运用的数据库是关系型数据库(Relational
Database卡塔尔国。一个数据库由多少个或一组数据表构成。每种数据库都是文件的款式存放在磁盘上,即对应于叁个大要文件。不相同的数据库,与物理文件对应的办法也不相像。对于dBASE,
FoxPro和Paradox格式的数据库来讲,三个数据表就是二个独立的数据库文件,而对于Microsoft
Access、Btrieve格式的数据库来讲,一个数据库文件能够包涵四个数据表。

2.2.2 数据表
/ Table

简单称谓表,由一组数据记录组成,数据库中的数据是以表为单位张开团队的。三个表是一组有关的按行排列的数额;每一个表中都包涵雷同类别的音讯。表实际上是二个二维表格,举个例子,叁个班全体学员的考试战绩,能够存放在叁个表中,表中的每一行对应三个学员,这一行李包裹涵学子的学号,姓名及各门课程战绩。

2.2.3 记录 /
Record

表中的每一行称为多个记录,它由若干个字段组成。

2.2.4 字段 /
Field

也称域。表中的每一列称为多个字段。每种字段都有对应的陈述音信,如数据类型、数据大幅等。

2.2.5 索引 /
Index

为了拉长访谈数据库的功效,能够对数据库使用索引。当数据库非常大时,为了寻找钦点的笔录,则应用索引和不接受索引的效率有非常的大差异。索引实际上是一种奇特类型的表,在那之中包涵关键字段的值(由客户定义卡塔尔(قطر‎和针对实际记录地点的指针,这几个值和指针根据一定的依次(也由客商定义卡塔尔存储,进而得以以异常快的快慢查找到所必要的多少记录。

2.2.6 查询 /
Query

一条SQL(布局化查询语言State of Qatar命令,用来从一个或多少个表中拿走一组钦点的笔录,也许对有个别表实践内定的操作。当从数据库中读取数据时,往往愿意读出的数目切合有个别条件,况兼能按有个别字段排序。使用SQL,可以使这一操作轻松达成並且越加有效。SQL是非进程化语言(有人称之为第四代语言State of Qatar,在用它寻觅钦点的笔录时,只需建议做哪些,不必表明什么做。各类语句能够看成是贰个询问(query卡塔尔,依据那个查询,能够赢得要求的询问结果。

2.2.7 过滤器
/ Filter

过滤器是数据库的一个组成都部队分,它把索引和排序结合起来,用来安装规范,然后遵照给定的标准输出所必要的数额。

2.2.8 视图 /
View

数码的视图指的是查找到(可能处理卡塔尔国的记录数和体现(也许拓宽管理State of Qatar那个记录的相继。在相仿景况下,视图由过滤器和目录调节。视图中并不存款和储蓄数据,视图是一种虚表。

2.3
数据库类型

2.3.1
关系型数据库

关系型数据库是指利用了事关模型来组织数量的数据库。

涉嫌模型是在1970年由IBM的研讨员E.F.Codd大学子首先提议的,在后来的数十年中,关系模型的定义得到了尽量的提升并稳步改为主流数据库布局的主流模型。

简单来讲的话,涉嫌模型指的便是二维表格模型,而三个关系型数据库便是由二维表及其之间的联络所结合的一个数据协会

关联模型中常用的概念:

关系:
能够驾驭为一张二维表,每一个关系都富有三个关乎名,正是平日说的表名

元组:
能够知晓为二维表中的一,在数据库中有的时候被叫做记录

属性:
能够清楚为二维表中的一,在数据库中时时被称呼字段

域:
属性的取值范围,也正是数据库中某一列的取值约束

关键字:
一组可以独一标记元组的属性,数据库中常称为主键,由一个或八个列组成

涉及方式:
指对关乎的描述。其格式为:关系名(属性1,属性2, … …
,属性NState of Qatar,在数据库中产生表结构

关系型数据库的独特之处:

轻巧掌握:
二维表构造是丰盛接近逻辑世界的多少个定义,关系模型相对网状、档次等别的模型来说更便于精通

使用方便:
通用的SQL语言使得操作关系型数据库非常平价

轻易维护:
丰裕的完整性(实体完整性、参照完整性和客商定义的完整性卡塔尔大大减低了数码冗余和数目不均等的概率。

2.3.2
非关系型数据库

非关系型数据库建议另一种思想,举例,以键值对存款和储蓄,且结构不稳定,每一个元组能够有不均等的字段,各种元组能够依靠必要扩大部分和煦的键值对,那样就不会局限于固定的布局,能够减去部分小时和空中的付出。使用这种措施,客户能够依赖必要去丰裕本人必要的字段,这样,为了赢得用户的例外新闻,不须求像关系型数据库中,要对多表实行关联合检查询。仅供给依靠id抽取相应的value就足以做到查询。但非关系型数据库由于非常少的羁绊,他也不可以知道提供像SQL所提供的where这种对于字段属性值情状的查询。并且难以体现统筹的完整性。他只相符储存一些较为轻易的数额,对于供给进行较复杂查询的多寡,SQL数据库显的一发方便。

鉴于非关系型数据库自身自然的多种性,以致并发的日子很短,因此,不想关系型数据库,有三种数据库可以一统江山,非关系型数据库超多,而且大多数都以开源的。

那一个数据库中,其实完成多数都比较轻便,除了部分共性外,相当的大片段都以针对一些特定的接受供给现身的,由此,对于此类应用,具备相当的高的特性。依靠布局化方法以至利用途合的不等,首要分为以下几类,

面向高品质并发读写的key-value数据库:

key-value数据库的第一特征正是具备异常高的并发读写质量,Redis,Tokyo
Cabinet,Flare正是那类的代表。

面向海量数据访谈的面向文书档案数据库:

这类数据库的特征是,能够在海量的数量中急迅的询问数据,规范代表为MongoDB以至CouchDB。

面向可扩充性的布满式数据库:

那类数据库想减轻的标题正是金钱观数据仓库储存在可扩张性上的毛病,那类数据库能够适应数据量的充实以致数据布局的变迁。

2.3.3 NoSQL

NoSQL(NoSQL = Not Only
SQL
State of Qatar,意即“不唯有是SQL”,是一项崭新的数据库革命性运动,开始时代就有人建议,发展至二〇〇八年趋向更高涨。NoSQL的跟随者们发起使用非关系型的数量存款和储蓄,相对于多如牛毛的关系型数据库行使,这一概念无疑是一种全新的思辨的流入。

2.4
数据库相关文化

2.4.1
Schema(模式)与dbo

有关Schema的知晓来自于那些链接

SQL中有贰个Schema的概念,实际上Schema就是数据库对象的汇集,那些集合包罗了表、视图、存款和储蓄过程、索引等,为了差距不一样的集中,就要求给分化的群集起不相同的名字,私下认可情况下八个客商对应一个集合,用户的schema名等于用户名,并作为该客户缺省schema。所以schema会集看上去像客商名。

一旦把database看作是一个库房,货仓比较多屋家(schema),七个schema代表贰个房屋,table可以充任是各种房间中的储物柜,user是各种schema的主人,有操作数据库中各种屋家的权利,正是说每一种数据库映射的user有每种schema(房间)的钥匙。

咱俩拜见二个表时,未有指明该表归属哪一个schema中的,系统就能够活动给大家在表上加上缺省的shema名。在数据库中二个对象的全体名字为schema.object,而不属user.object。

在MySQL中开创三个Schema和创造叁个Database的效果近似是相仿的,可是在sqlserver和orcal数据库中成效又是例外的。

在SQL Server
二零零零中,user和schema总有一层隐含的涉嫌,让大家比超少意识到骨子里user和schema是三种何啻天壤的概念,假如大家在某一数据库中开创了用户Bosco,那么当时后台也为大家暗中认可的始建了schema【Bosco】,schema的名字和user的名字大同小异。

在SQL Server
二〇〇五中,为了向后极度,当用sp_adduser存款和储蓄进程创设叁个用户的时候,sqlserver二零零六相同的时间也开创了多个和客户名相近的schema,不过这一个蕴藏进程是为了向后十一分才保留的,当我们用create
user成立数据库客商时,我们得感觉该客商钦定四个一度存在的schema作为私下认可的schema,假诺大家不指定,则该顾客所私下认可的schema即为dbo
schema,dbo房间(schema)好比二个大的公家房间,在当下登陆客户并未有私下认可schema的前提下,假让你在大货仓中展开部分操作,比如create
table,如果未有拟定一定的房间(schema),那么你的物料就一定要放进公共的dbo房间(schema)了。不过假设当前报到顾客有私下认可的schema,那么所做的万事操作都以在默许的schema上拓展。

Oracle数据库中无法新建一个schema,要想创设叁个schema,只可以通过创设四个客户的主意解决,在创制二个客商的相同的时候为这几个顾客创制一个与客户名同名的schem并视作该顾客的缺省shcema。即schema的个数同user的个数相同,并且schema名字同user名字一一对应何况肖似。

 

普通职业中常常境遇相像的标题:把某部服务器上的少数钦命的表同步到其余一台服务器。

参谋链接


就好像需要用SSIS只怕别的ETL工作超级轻便完成,比如用SSIS的话,就能够会存在一定部分每每的手工业操作。

建源的数据库消息,目的的数据库音信,假使是多少个表,须求三个二个地拉source和target,然后三个一个地mapping,然后运维落成多少同步。

然后相当的大概,那些workflow使用也就那样一回,就葬身鱼腹了,却同样要浪费时间去做这么些ETL。

敏捷数据同步达成

于是在想,可不可能快捷完结肖似供给,尽最大程度裁减重复的手工业操作?肖似基于命令行的情势,轻便飞快,无需太多的手动操作。

于是就有了本文,基于Python,快捷实现SQL
Server的数据库之间的多寡同步操作,后边又有些扩展了一晃,能够达成不相同服务器的数据库之间的表布局,表对应的数量,存款和储蓄进度,函数,客户自定义类型表的一路

日前支撑在三个SQL
Server数据源之间:每一趟同步一张或然多张表/存储进程,也得以联手整个数据库的全身体表面/存款和储蓄进程。

辅助sqlserver二〇一二以上版本

亟待考虑到部分宗旨的校验难点:在源服务器上,须要一起的指标是或不是留存,大概输入的靶子是否存在于源服务器的数据Curry。

在目的服务器上,对于表的联合签字:

1,表的留存依赖于schema,必要思考到表的schema是还是不是存在,就算一纸空文先在target库上创建表对应的schema

2,target表中是否有数据?倘使有数量,是还是不是以覆盖的秘诀执行

对此仓库储存进度的联手:

1,相同于表,须要思考存款和储蓄进程的schema是不是留存,要是不设有先在target库上创制表对应的schema2,相像于表,arget数据库中是还是不是业已存在对应的积存进度,是还是不是以隐瞒的措施举行3,存储进程也许依附于b表,有个别函数,顾客自定义表变量等等,同步存款和储蓄进度的时候需求先同步信赖的指标,这点比较复杂,达成进程中相遇在不菲浩大的坑

只怕存在对象A依赖于对象B,对象B正视于对象C……,这里有一点点递归的意趣

那点导致了重构大量的代码,一开首都以全盘托出的一块,不大概落到实处这一个逻辑,切实体会到代码的“单一职分”原则

参数说明

参数表明如下,大的席卷四类:

1,源服务器新闻 ,未有顾客名密码的状态下,使用windows居民身份表明方式

2,目的服务器消息,未有客户名密码的动静下,使用windows身份认证方式

3,同步的指标类型以致对象

4,同步的目的在对象服务器上设有的情事下,是还是不是强逼覆盖

实际上在一道数据的时候,也能够把须求一同的行数提收取来做参数,比较容易,这里暂风还未有做。

例如要求飞速搭建三个测量检验情状,须要一块所有的表结议和每种表的一部分数据就能够。

表以致数额同步

表同步的规律是,创造目的表,遍历源数据的表,生成insert into
values(***),(***),(***State of Qatar格式的sql,然后插入指标数据库,这里大致步骤如下:

1,表信任于schema,所以同步表从前先同步schema

2,强逼覆盖的情事下,会drop掉目的表,幸免指标表与源表构造不平等,非免强覆盖的情况下,借使字段不均等,则抛出十一分

3,同步表布局,包蕴字段,索引,节制等等,可是不能够支撑外键,特意去掉了外键,用脑筋想怎么?因吹斯汀。

4,需求筛选出来非总计列字段,insert语句只可以是非总括列字段

5,转义管理,在拼凑SQL的时候,须求张开转义管理,否则会促成SQL语句错误,方今管理了字符串中的’字符,二进制字段,时间字段的转义管理

6,鉴于insert into values(***),(***),(***)语法上同意的最大值是1000,因而每生成1000条数据,就协同叁次

7,自增列的identity_insert标识张开与关闭管理

运用如下参数,同步源数据库的三张表到指标数据库,因为那边是在本机命名实例下测验,由此实例名和端口号输入

实行同步的作用

说明:

1,假如输入obj_type=”tab”
且-obj=为None的事态下,会同步源数据库中的全数表。2,那一个频率决计于机器质量和网络传输,本机测量试验的话,每秒中能够付出3到4次,相当于每分钟能够交到3000~4000行左右的数额。

已知的主题材料:

1,当表的目录为filter
index的时候,不只怕转移包涵where条件的目录创造语句,这么些看起来蛋疼的表布局导出语句,一时半刻没时间改它。2,临时不扶植任何少用的品类字段,比如地理空间字段什么的。

存款和储蓄进程对象的一路

仓库储存进程同步的规律是,在源数据库上扭转成立存款和储蓄进度的话语,然后写入指标库,这里大致步骤如下:1,存款和储蓄进度重视于schema,所以同步存储进度从前先同步schema2,同步的进程会检查重视对象,假使依据别的对象,暂停当前指标同步,先同步重视对象3,重复第二手续,直至达成4,对于仓库储存进度的贰只,即便是威迫覆盖的话,强迫覆盖仅仅对存款和储蓄进度自个儿生效,对信任对象并不见到成效,假设依靠对象不设有,就成立,不然不做其余专门的工作

选用如下参数,同步源数据库的五个存款和储蓄进度到对象数据库,因为那边是在本机命名实例下测验,由此实例名和端口号输入

证实:测验要共同的仓库储存进程之一为[dbo].[sp_test01],它依附于任何七个对象:dbo.table01和dbo.fn_test01()

create proc [dbo].[sp_test01]asbegin set no count on; delete from dbo.table01 where id = 1000 select dbo.fn_test01()end

而dbo.fn_test01(卡塔尔国的如下,信任于此外四个目的:dbo.table02

create function [dbo].[fn_test01]()RETURNS intASBEGIN declare @count int = 0 select @count = count(1) from dbo.table02 return @countEND

于是,这么些测量试验的[dbo].[sp_test01]就借助于任何对象,假设其依靠的对象海市蜃楼,同步的时候,仅仅一同那一个蕴藏进度自身,是绝非意思的

一起某三个指标的信赖性对象,使用如下SQL查出来对象依赖音信,由此这里就少有递进,同步信任对象。这里有如于同步A的时候,A信赖于B和C,然后截至同步A,先同步B和C,同步B大概C的时候,恐怕又凭仗于别的对象,然后继续先同步其借助对象。

效果与利益如下

比如输入obj_type=”sp”
且-obj=为None的情事下,会同步源数据库中的全数存款和储蓄进度以至其依靠对象

已知的主题材料:

1,加密的仓库储存进程依然函数是力不能及贯彻同步的,因为不或许转移创造对象的剧本1,table
type的协同也是四个蛋疼的历程,前段时间扶植,可是扶助的并不佳,原因是成立table
type在此以前,先删除重视于table type的指标,不然无法删除与创造。

专程表明

依附对象的消除,依旧比较蛋疼的

若是在私下认可schema为dbo的目的,在存款和储蓄进程也许函数中向来不写schema,使用
sys.dm_sql_referenced_entities这么些系统函数是不可能找到其依靠的目的的,奇葩的是足以找到schema的等级次序,却不曾重返对象自己。

这或多或少造成在代码中少见浓郁,举行了长日子的debug,完全没有想到这几个函数是那几个鸟样子,因为这里找到依赖对象的花色,却找不到目的自己,次奥!!!其它一种情况就是动态SQL了,不恐怕运用
sys.dm_sql_referenced_entities这么些系统函数找到其依靠的靶子。

其它对象的联手

协助其余数据库对象的合营,举例function,table
type等,因为能够在一同别的存储进度对象的时候顺便的同步function,table
type,那一个与表或许存储进程看似,不做过多表明。

已知难点:

1,20一九零六122030:经测验,近期暂且不帮助Sequence对象的联手。

内需改进的地点

1,代码结构优化,越发明显和条例的布局2,数据同步的频率难题,对于多表的导入导出操作,重视于单线程,多少个大表导出串行的话,恐怕存在功效上的瓶颈,如何依照表的数据量,尽只怕平均地分配多七个线程中,提高效用3,尤其友好清晰的百般提醒以致日志记录,生成导出日志新闻。4,异构数据同步,MySQL《==》SQL
Server《==》Oracle《==》PGSQL

代码重午节写好了,近日抽空进行了部分测量检验以致bug
fix,应该还潜在不菲茫然的bug,专门的职业量比想象中的大的多了去了。

# -*- coding: utf-8 -*-# !/usr/bin/env python3__author__ = 'MSSQL123'__date__ = '2019-06-07 09:36'import osimport sysimport timeimport datetimeimport pymssqlfrom decimal import Decimalusage = ''' -----parameter explain----- source database parameter -s_h : soure database host ----- must require parameter -s_i : soure database instace name ----- default instance name MSSQL -s_d : soure database name ----- must require parameter -s_u : soure database login ----- default windows identifier -s_p : soure database login password ----- must require when s_u is not null -s_P : soure database instance port ----- default port 1433 target database parameter -t_h : target database host ----- must require parameter -t_i : target database instace name ----- default instance name MSSQL -t_d : target database name ----- must require parameter -t_u : target database login ----- default windows identifier -t_p : target database login password ----- must require when s_u is not null -t_P : target database instance port ----- default port 1433 sync object parameter -obj_type : table or sp or function or other databse object ----- tab or sp or fn or tp -obj : table|sp|function|type name ----- whick table or sp sync overwirte parameter -f : force overwirte target database object ----- F or N --help: help document Example: python DataTransfer.py -s_h=127.0.0.1 -s_P=1433 -s_i="MSSQL" -s_d="DB01" -obj_type="tab" -obj="dbo.t1,dbo.t2" -t_h=127.0.0.1 -t_P=1433 -t_i="MSSQL" -t_d="DB02" -f="Y" python DataTransfer.py -s_h=127.0.0.1 -s_P=1433 -s_i="MSSQL" -s_d="DB01" -obj_type="sp" -obj="dbo.sp1,dbo.sp2" -t_h=127.0.0.1 -t_P=1433 -t_i="MSSQL" -t_d="DB02" -f="Y" '''class SyncDatabaseObject(object): # source databse s_h = None s_i = None s_P = None s_u = None s_p = None s_d = None # obj type s_obj_type = None # sync objects s_obj = None # target database t_h = None t_i = None t_P = None t_u = None t_p = None t_d = None f = None file_path = None def __init__(self, *args, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) # connect to sqlserver def get_connect(self, _h, _i, _P, _u, _p, _d): cursor = False try: if (_u) and (_p): conn = pymssql.connect(host=_h, server=_i, port=_P, user=_u, password=_p, database=_d) else: conn = pymssql.connect(host=_h, server=_i, port=_P, database=_d) if (conn): return conn except: raise return conn # check connection def validated_connect(self, _h, _i, _P, _u, _p, _d): if not (self.get_connect(_h, _i, _P, _u, _p, _d)): print("connect to " + str(_h) + " failed,please check you parameter") exit(0) ''' this is supposed to be a valid object name just like xxx_name,or dbo.xxx_name,or [schema].xxx_name or schema.[xxx_name] then transfer this kind of valid object name to format object name like [dbo].[xxx_name](give a default dbo schema name when no schema name) other format object name consider as unvalid,will be rasie error in process format object name 1,xxx_name ====== [dbo].[xxx_name] 2,dbo.xxx_name ====== [dbo].[xxx_name] 3,[schema].xxx_name ====== [dbo].[xxx_name] 3,schema.xxx_name ====== [schema].[xxx_name] 4,[schema].[xxx_name] ====== [schema].[xxx_name] 5,[schema].[xxx_name ====== rasie error format message ''' @staticmethod def format_object_name(name): format_name = "" if ("." in name): schema_name = name[0:name.find(".")] object_name = name[name.find(".") + 1:] if not ("[" in schema_name): schema_name = "[" + schema_name + "]" if not ("[" in object_name): object_name = "[" + object_name + "]" format_name = schema_name + "." + object_name else: if ("[" in name): format_name = "[dbo]." + name else: format_name = "[dbo]." + "[" + name + "]" return format_name ''' check user input object is a valid object ''' def exits_object(self, conn, name): conn = conn cursor_source = conn.cursor() # get object by name from source db sql_script = r'''select top 1 1 from ( select concat(QUOTENAME(schema_name(schema_id)),'.',QUOTENAME(name)) as obj_name from sys.objects union all select concat(QUOTENAME(schema_name(schema_id)),'.',QUOTENAME(name)) as obj_name from sys.types )t where obj_name = '{0}' '''.format(self.format_object_name(name)) cursor_source.execute(sql_script) result = cursor_source.fetchall() if not result: return 0 else: return 1 conn.cursor.close() conn.close() # table variable sync def sync_table_variable(self, tab_name, is_reference): conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() if (self.exits_object(conn_source, self.format_object_name(tab_name)))  0: pass else: print("----------------------- warning message -----------------------") print("--------warning: object " + tab_name + " not existing in source database ------------") print("----------------------- warning message -----------------------") print() return exists_in_target = 0 sql_script = r'''select top 1 1 from sys.table_types tp where is_user_defined = 1 and concat(QUOTENAME(schema_name(tp.schema_id)),'.',QUOTENAME(tp.name)) = '{0}' ''' \ .format((self.format_object_name(tab_name))) # if the table schema exists in target server,skip cursor_target.execute(sql_script) exists_in_target = cursor_target.fetchone() # weather exists in target server database if (self.f == "Y"): if (is_reference != "Y"): # skiped,table type can not drop when used by sp sql_script = r''' if OBJECT_ID('{0}') is not null drop type {0} '''.format(self.format_object_name(tab_name)) cursor_target.execute(sql_script) conn_target.commit() else: if exists_in_target: print("----------------------- warning message -----------------------") print("the target table type " + tab_name + " exists ,skiped sync table type from source") print("----------------------- warning message -----------------------") print() return sql_script = r''' DECLARE @SQL NVARCHAR(MAX) = '' SELECT @SQL = 'CREATE TYPE ' + '{0}' + 'AS TABLE' + CHAR(13) + '(' + CHAR(13) + STUFF(( SELECT CHAR(13) + ' , [' + c.name + '] ' + CASE WHEN c.is_computed = 1 THEN 'AS ' + OBJECT_DEFINITION(c.[object_id], c.column_id) ELSE CASE WHEN c.system_type_id != c.user_type_id THEN '[' + SCHEMA_NAME(tp.[schema_id]) + '].[' + tp.name + ']' ELSE '[' + UPPER(y.name) + ']' END + CASE WHEN y.name IN ('varchar', 'char', 'varbinary', 'binary') THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(5)) END + ')' WHEN y.name IN ('nvarchar', 'nchar') THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(5)) END + ')' WHEN y.name IN ('datetime2', 'time2', 'datetimeoffset') THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')' WHEN y.name = 'decimal' THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')' ELSE '' END + CASE WHEN c.collation_name IS NOT NULL AND c.system_type_id = c.user_type_id THEN ' COLLATE ' + c.collation_name ELSE '' END + CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END + CASE WHEN c.default_object_id != 0 THEN ' CONSTRAINT [' + OBJECT_NAME(c.default_object_id) + ']' + ' DEFAULT ' + OBJECT_DEFINITION(c.default_object_id) ELSE '' END END From sys.table_types tp Inner join sys.columns c on c.object_id = tp.type_table_object_id Inner join sys.types y ON y.system_type_id = c.system_type_id WHERE tp.is_user_defined = 1 and y.name'sysname' and concat(QUOTENAME(schema_name(tp.schema_id)),'.',QUOTENAME(tp.name)) = '{0}' ORDER BY c.column_id FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 7, ' ') + ');' select @SQL as script '''.format(self.format_object_name(self.format_object_name((tab_name)))) cursor_target = conn_target.cursor() cursor_source.execute(sql_script) row = cursor_source.fetchone() try: if not exists_in_target: # execute the script on target server cursor_target.execute(str(row[0])) # drop current stored_procudre if exists conn_target.commit() print("*************table type " + self.format_object_name(tab_name) + " synced *********************") print() # give a blank row when finish except: print("----------------------- error message -----------------------") print("-----------table type " + self.format_object_name(tab_name) + " synced error ---------------") print("----------------------- error message -----------------------") print() # raise cursor_source.close() conn_source.close() cursor_target.close() conn_target.close() # schema sync def sync_schema(self): conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() arr_schema = [] # get all table in database when not define table name schema_result = cursor_source.execute(r''' select name from sys.schemas where schema_id4 and schema_id16384 ''') for row in cursor_source.fetchall(): cursor_target.execute(r''' if not exists(select * from sys.schemas where name = '{0}') begin exec('create schema [{0}]') end '''.format(str(row[0]))) conn_target.commit() cursor_source.close() conn_source.close() cursor_target.close() conn_target.close() def sync_table_schema_byname(self, tab_name, is_reference): conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() if (self.exits_object(conn_source, self.format_object_name(tab_name)) == 0): print("----------------------- warning message -----------------------") print("---------------warning: object " + tab_name + " not existing in source database ----------------") print("----------------------- warning message -----------------------") print() return # if exists a reference table for sp,not sync the table agagin if (self.exits_object(conn_target, self.format_object_name(tab_name))  0): if (self.f != "Y"): print("----------------------- warning message -----------------------") print("---------------warning: object " + tab_name + " existing in target database ----------------") print("----------------------- warning message -----------------------") print() return sql_script = r''' select top 1 1 from sys.tables where type_desc = 'USER_TABLE' and concat(QUOTENAME(schema_name(schema_id)),'.',QUOTENAME(name)) = '{0}' '''.format((self.format_object_name(tab_name))) # if the table schema exists in target server,skip cursor_target.execute(sql_script) exists_in_target = cursor_target.fetchone() if exists_in_target: if (self.f == "Y"): if (is_reference != "Y"): cursor_target.execute("drop table {0}".format(tab_name)) else: print("----------------------- warning message -----------------------") print("the target table " + tab_name + " exists ,skiped sync table schema from source") print("----------------------- warning message -----------------------") print() return sql_script = r''' DECLARE @object_name SYSNAME , @object_id INT SELECT @object_name = '[' + s.name + '].[' + o.name + ']' , @object_id = o.[object_id] FROM sys.objects o WITH (NOWAIT) JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id] WHERE QUOTENAME(s.name) + '.' + QUOTENAME(o.name) = '{0}' AND o.[type] = 'U' AND o.is_ms_shipped = 0 DECLARE @SQL NVARCHAR(MAX) = '' ;WITH index_column AS ( SELECT ic.[object_id] , ic.index_id , ic.is_descending_key , ic.is_included_column , c.name FROM sys.index_columns ic WITH (NOWAIT) JOIN sys.columns c WITH (NOWAIT) ON ic.[object_id] = c.[object_id] AND ic.column_id = c.column_id WHERE ic.[object_id] = @object_id ), fk_columns AS ( SELECT k.constraint_object_id , cname = c.name , rcname = rc.name FROM sys.foreign_key_columns k WITH (NOWAIT) JOIN sys.columns rc WITH (NOWAIT) ON rc.[object_id] = k.referenced_object_id AND rc.column_id = k.referenced_column_id JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = k.parent_object_id AND c.column_id = k.parent_column_id WHERE k.parent_object_id = @object_id ) SELECT @SQL = 'CREATE TABLE ' + @object_name + '' + '(' + '' + STUFF(( SELECT '' + ', [' + c.name + '] ' + CASE WHEN c.is_computed = 1 THEN 'AS ' + cc.[definition] ELSE UPPER(tp.name) + CASE WHEN tp.name IN ('varchar', 'char', 'varbinary', 'binary', 'text') THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(5)) END + ')' WHEN tp.name IN ('nvarchar', 'nchar') THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(5)) END + ')' WHEN tp.name IN ('datetime2', 'time2', 'datetimeoffset') THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')' WHEN tp.name = 'decimal' THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')' ELSE '' END + CASE WHEN c.collation_name IS NOT NULL THEN ' COLLATE ' + c.collation_name ELSE '' END + CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END + CASE WHEN dc.[definition] IS NOT NULL THEN ' DEFAULT' + dc.[definition] ELSE '' END + CASE WHEN ic.is_identity = 1 THEN ' IDENTITY(' + CAST(ISNULL( /*ic.seed_value*/ 1, '0') AS CHAR(1)) + ',' + CAST(ISNULL(ic.increment_value, '1') AS CHAR(1)) + ')' ELSE '' END END + '' FROM sys.columns c WITH (NOWAIT) JOIN sys.types tp WITH (NOWAIT) ON c.user_type_id = tp.user_type_id LEFT JOIN sys.computed_columns cc WITH (NOWAIT) ON c.[object_id] = cc.[object_id] AND c.column_id = cc.column_id LEFT JOIN sys.default_constraints dc WITH (NOWAIT) ON c.default_object_id != 0 AND c.[object_id] = dc.parent_object_id AND c.column_id = dc.parent_column_id LEFT JOIN sys.identity_columns ic WITH (NOWAIT) ON c.is_identity = 1 AND c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id WHERE c.[object_id] = @object_id ORDER BY c.column_id FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' + ' ') + ISNULL((SELECT '' + ', CONSTRAINT [' + k.name + '] PRIMARY KEY (' + (SELECT STUFF(( SELECT ', [' + c.name + '] ' + CASE WHEN ic.is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END FROM sys.index_columns ic WITH (NOWAIT) JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id WHERE ic.is_included_column = 0 AND ic.[object_id] = k.parent_object_id AND ic.index_id = k.unique_index_id FOR XML PATH(N''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')) + ')' + '' FROM sys.key_constraints k WITH (NOWAIT) WHERE k.parent_object_id = @object_id AND k.[type] = 'PK'), '') + ')' + '' + ISNULL((SELECT ( SELECT '' + 'ALTER TABLE ' + @object_name + ' WITH' + CASE WHEN fk.is_not_trusted = 1 THEN ' NOCHECK' ELSE ' CHECK' END + ' ADD CONSTRAINT [' + fk.name + '] FOREIGN KEY(' + STUFF(( SELECT ', [' + k.cname + ']' FROM fk_columns k WHERE k.constraint_object_id = fk.[object_id] and 1=2 FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')' + ' REFERENCES [' + SCHEMA_NAME(ro.[schema_id]) + '].[' + ro.name + '] (' + STUFF(( SELECT ', [' + k.rcname + ']' FROM fk_columns k WHERE k.constraint_object_id = fk.[object_id] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')' + CASE WHEN fk.delete_referential_action = 1 THEN ' ON DELETE CASCADE' WHEN fk.delete_referential_action = 2 THEN ' ON DELETE SET NULL' WHEN fk.delete_referential_action = 3 THEN ' ON DELETE SET DEFAULT' ELSE '' END + CASE WHEN fk.update_referential_action = 1 THEN ' ON UPDATE CASCADE' WHEN fk.update_referential_action = 2 THEN ' ON UPDATE SET NULL' WHEN fk.update_referential_action = 3 THEN ' ON UPDATE SET DEFAULT' ELSE '' END + '' + 'ALTER TABLE ' + @object_name + ' CHECK CONSTRAINT [' + fk.name + ']' + '' FROM sys.foreign_keys fk WITH (NOWAIT) JOIN sys.objects ro WITH (NOWAIT) ON ro.[object_id] = fk.referenced_object_id WHERE fk.parent_object_id = @object_id FOR XML PATH(N''), TYPE).value('.', 'NVARCHAR(MAX)')), '') + ISNULL(((SELECT '' + 'CREATE' + CASE WHEN i.is_unique = 1 THEN ' UNIQUE' ELSE '' END + ' NONCLUSTERED INDEX [' + i.name + '] ON ' + @object_name + ' (' + STUFF(( SELECT ', [' + c.name + ']' + CASE WHEN c.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END FROM index_column c WHERE c.is_included_column = 0 AND c.index_id = i.index_id FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')' + ISNULL('' + 'INCLUDE (' + STUFF(( SELECT ', [' + c.name + ']' FROM index_column c WHERE c.is_included_column = 1 AND c.index_id = i.index_id FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')', '') + '' FROM sys.indexes i WITH (NOWAIT) WHERE i.[object_id] = @object_id AND i.is_primary_key = 0 AND i.[type] = 2 FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ), '') select @SQL as script '''.format(self.format_object_name(tab_name)) cursor_target = conn_target.cursor() cursor_source.execute(sql_script) row = cursor_source.fetchone() if not row[0]: return try: cursor_target.execute(row[0]) # drop current table schema if exists conn_target.commit() print("*************schema " + self.format_object_name(tab_name) + " synced *************") print() # give a blank row when finish except: print("----------------------- warning message -----------------------") print("-----------schema " + self.format_object_name(tab_name) + " synced failed---------------") print("----------------------- warning message -----------------------") print() cursor_source.close() conn_source.close() cursor_target.close() conn_target.close() def get_table_column(self, conn, tab_name): column_names = "" conn = conn cursor_source = conn.cursor() # get object by name from source db sql_script = r'''select name from sys.columns where object_id = object_id('{0}') and is_computed=0 order by object_id '''.format(self.format_object_name(tab_name)) cursor_source.execute(sql_script) result = cursor_source.fetchall() for row in result: column_names = column_names + row[0] + "," return column_names[0:len(column_names) - 1] conn.cursor.close() conn.close() def sync_table_schema(self): #default not sync by referenced other object is_reference = "N" conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() arr_table = [] if (self.s_obj): for tab_name in self.s_obj.split(","): if (tab_name) and (self.exits_object(conn_source, tab_name)0): self.sync_table_schema_byname(tab_name, is_reference) else: print("----------------------- warning message -----------------------") print("-----------schema " + self.format_object_name(tab_name) + " not existing in source database---------------") print("----------------------- warning message -----------------------") print() else: # sync all tables # get all table in database when not define table name sql_script = ''' SELECT QUOTENAME(s.name)+'.'+ QUOTENAME(o.name) FROM sys.objects o WITH (NOWAIT) JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id] WHERE o.[type] = 'U' AND o.is_ms_shipped = 0 ''' cursor_source.execute(sql_script) for row in cursor_source.fetchall(): self.sync_table_schema_byname(str(row[0]), is_reference) # sync data from soure table to target table def sync_table_data(self): conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() arr_table = [] if (self.s_obj): arr_table = self.s_obj.split(',') for tab_name in arr_table: if (self.exits_object(conn_target, self.format_object_name(tab_name)) == 0): arr_table.remove(tab_name) print("----------------- warning message -----------------------") print("----------------- warning: table " + tab_name + " not existing in target database ---------------------") print("----------------- warning message -----------------------") else: # get all table in database when not define table name tab_result = cursor_source.execute(r''' SELECT QUOTENAME(s.name)+'.'+ QUOTENAME(o.name) FROM sys.objects o WITH (NOWAIT) JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id] WHERE o.[type] = 'U' AND o.is_ms_shipped = 0 ''') for row in cursor_source.fetchall(): arr_table.append(str(row[0])) insert_columns = "" insert_columns = self.get_table_column(conn_source, tab_name) for tab_name in arr_table: if (self.f != "Y"): sql_script = "select top 1 {0} from {1} ".format(insert_columns, tab_name) # if exists data in target table,break cursor_target.execute(sql_script) exists = cursor_target.fetchone() if exists: print("----------------------- warning message -----------------------") print("the target table " + tab_name + " exists data,skiped sync table type from source") print("----------------------- warning message -----------------------") print() continue else: sql_script = "truncate table {0} ".format(tab_name) # if exists data in target table,break cursor_target.execute(sql_script) conn_target.commit() insert_columns = "" insert_columns = self.get_table_column(conn_source, tab_name) insert_prefix = "" # weather has identity column cursor_source.execute(r'''select 1 from sys.columns where object_id = OBJECT_ID('{0}') and is_identity =1 '''.format(tab_name)) exists_identity = None exists_identity = cursor_source.fetchone() if (exists_identity): insert_prefix = "set identity_insert {0} on; ".format(tab_name) # data source insert_sql = "" values_sql = "" current_row = "" counter = 0 sql_script = r''' select {0} from {1} '''.format(insert_columns, tab_name) cursor_source.execute(sql_script) # create insert columns ''' for field in cursor_source.description: insert_columns = insert_columns + str(field[0]) + "," insert_columns = insert_columns[0:len(insert_columns) - 1] ''' insert_prefix = insert_prefix + "insert into {0} ({1}) values ".format(tab_name, insert_columns) for row in cursor_source.fetchall(): counter = counter + 1 for key in row: if (str(key) == "None"): current_row = current_row + r''' null, ''' else: if (type(key) is datetime.datetime): current_row = current_row + r''' '{0}', '''.format(str(key)[0:23]) elif (type(key) is str): # 我槽!!!,这里又有一个坑: current_row = current_row + r''' '{0}', '''.format( key.replace("'", "''").replace('\u0000', '').replace('\x00', '')) elif (type(key) is Decimal): d = Decimal(key) s = '{0:f}'.format(d) current_row = current_row + r''' '{0}', '''.format(s) elif (type(key) is bytes): # print(hex(int.from_bytes(key, 'big', signed=True) )) current_row = current_row + r''' {0}, '''.format( hex(int.from_bytes(key, 'big', signed=False))) else: current_row = current_row + r''' '{0}', '''.format(key) current_row = current_row[0:len(current_row) - 2] # remove the the last one char "," values_sql = values_sql + "(" + current_row + ")," current_row = "" # execute the one batch when if (counter == 1000): insert_sql = insert_prefix + values_sql insert_sql = insert_sql[0:len(insert_sql) - 1] # remove the the last one char "," if (exists_identity): insert_sql = insert_sql + " ;set identity_insert {0} off;".format(tab_name) try: cursor_target.execute(insert_sql) except: print( "----------------------error " + tab_name + " data synced failed-------------------------") raise conn_target.commit() insert_sql = "" values_sql = "" current_row = "" counter = 0 print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "*************** " + self.format_object_name( tab_name) + " " + str(1000) + " rows synced *************") if (values_sql): insert_sql = insert_prefix + values_sql insert_sql = insert_sql[0:len(insert_sql) - 1] # remove the the last one char "," if (exists_identity): insert_sql = insert_sql + " ; set identity_insert {0} off;".format(tab_name) # execute the last batch try: cursor_target.execute(insert_sql) except: print("------------------error " + tab_name + " data synced failed------------------------") raise conn_target.commit() insert_sql = "" values_sql = "" current_row = "" print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "*************** " + self.format_object_name( tab_name) + " " + str( counter) + " rows synced *************") print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "----------------synced " + self.format_object_name( tab_name) + " data finished---------------") print() cursor_source.close() conn_source.close() cursor_target.close() conn_target.close() def sync_dependent_object(self, obj_name): # 强制覆盖,不需要对依赖对象生效,如果是因为属于依赖对象而被同步的,先检查target中是否存在,如果存在就不继续同步,这里打一个标记来实现 is_refernece = "Y" conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() ''' find dependent objects if exists dependent objects,sync Dependent objects objects in advance ''' sql_check_dependent = r''' SELECT * FROM ( SELECT distinct rtrim(lower(s.type)) COLLATE Chinese_PRC_CI_AS as obj_type, QUOTENAME(d.referenced_schema_name)+'.'+QUOTENAME(d.referenced_entity_name) COLLATE Chinese_PRC_CI_AS as obj FROM sys.dm_sql_referenced_entities('{0}','OBJECT') as d inner join sys.sysobjects s on s.id = d.referenced_id union all SELECT distinct rtrim(lower(d.referenced_class_desc)) COLLATE Chinese_PRC_CI_AS as obj_type, QUOTENAME(d.referenced_schema_name)+'.'+QUOTENAME(d.referenced_entity_name) COLLATE Chinese_PRC_CI_AS as obj FROM sys.dm_sql_referenced_entities('{0}','OBJECT') as d inner join sys.types s on s.user_type_id = d.referenced_id )t '''.format(self.format_object_name(obj_name)) cursor_source.execute(sql_check_dependent) result = cursor_source.fetchall() for row in result: if row[1]: if (row[0] == "u"): if (row[1]): self.sync_table_schema_byname(row[1], is_refernece) elif (row[0] == "fn" or row[0] == "if"): if (row[1]): self.sync_procudre_by_name("f", row[1], is_refernece) elif (row[0] == "type"): if (row[1]): self.sync_table_variable(row[1], is_refernece) def sync_procudre_by_name(self, type, obj_name, is_reference): conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() if (self.exits_object(conn_source, self.format_object_name(obj_name)) == 0): print("---------------warning message----------------") print("---------------warning: object " + obj_name + " not existing in source database ----------------") print("---------------warning message----------------") print() return if (self.exits_object(conn_target, self.format_object_name(obj_name))  0): if (self.f != "Y"): print("---------------warning message----------------") print("---------------warning: object " + obj_name + " existing in target database ----------------") print("---------------warning message----------------") print() return ''' 本来想直接生成删除语句的: 这里有一个该死的转义,怎么都弄不好,中午先去吃饭吧, 下午回来想了一下,换一种方式,不要死磕转义问题了 sql_script = select 'if object_id('+''''+QUOTENAME(schema_name(uid))+ '' + QUOTENAME(name)+''''+') is not null ' +' drop proc '+QUOTENAME(schema_name(uid))+ '.' + QUOTENAME(name) , OBJECT_DEFINITION(id) from sys.sysobjects where xtype = 'P' and uid not in (16,19) ''' sql_script = r''' select QUOTENAME(schema_name(uid))+'.'+QUOTENAME(name), OBJECT_DEFINITION(id) from sys.sysobjects where xtype in ('P','IF','FN') and uid not in (16,19) ''' if (obj_name): sql_script = sql_script + " and QUOTENAME(schema_name(uid))+ '.' + QUOTENAME(name) ='{0}' ".format( self.format_object_name(obj_name)) cursor_source.execute(sql_script) row = cursor_source.fetchone() try: if type == "f": sql_script = r''' if object_id('{0}') is not null drop function {0} '''.format(self.format_object_name(row[0])) elif type == "p": sql_script = r''' if object_id('{0}') is not null drop proc {0} '''.format(self.format_object_name(row[0])) cursor_target.execute(sql_script) # drop current stored_procudre if exists conn_target.commit() # sync dependent object if (is_reference != "N"): self.sync_dependent_object(self.format_object_name(row[0])) # sync object it self cursor_target.execute(str(row[1])) # execute create stored_procudre script conn_target.commit() print("*************sync sp: " + self.format_object_name(row[0]) + " finished *****************") print() except: print("---------------error message----------------") print("------------------ sync " + row[0] + "sp error --------------------------") print("---------------error message----------------") print() cursor_source.close() conn_source.close() cursor_target.close() conn_target.close() def sync_procudre(self, type): is_reference = "N" conn_source = self.get_connect(self.s_h, self.s_i, self.s_P, self.s_u, self.s_p, self.s_d) conn_target = self.get_connect(self.t_h, self.t_i, self.t_P, self.t_u, self.t_p, self.t_d) cursor_source = conn_source.cursor() cursor_target = conn_target.cursor() if (self.s_obj): for proc_name in self.s_obj.split(","): self.sync_dependent_object(proc_name) self.sync_procudre_by_name(type, proc_name, is_reference) # sync all sp and function else: sql_script = r''' select QUOTENAME(schema_name(uid))+'.'+QUOTENAME(name), OBJECT_DEFINITION(id) from sys.sysobjects where xtype = upper('{0}') and uid not in (16,19) '''.format(type) cursor_source.execute(sql_script) for row in cursor_source.fetchall(): self.sync_dependent_object(row[0]) self.sync_procudre_by_name(type, row[0], is_reference)if __name__ == "__main__": ''' sync = SyncDatabaseObject(s_h="127.0.0.1", s_i = "sql2017", s_P = 49744, s_d="DB01", t_h="127.0.0.1", t_i="sql2017", t_P=49744, t_d="DB02", s_obj_type = "sp", s_obj = "dbo.sp_test01", f="Y") sync.sync_procudre("p") ''' p_s_h = "" p_s_i = "MSSQL" p_s_P = 1433 p_s_d = "" p_s_u = None p_s_p = None p_s_obj = "" p_type = "" p_t_s = "" p_t_i = "MSSQL" p_t_P = "1433" p_t_d = "" p_t_u = None p_t_p = None # force conver target database object,default not force cover target database object p_f = "N" # sync obj type table|sp p_obj_type = None # sync whick database object p_obj = None if len(sys.argv) == 1: print(usage) sys.exit(1) elif sys.argv[1] == '--help': print(usage) sys.exit() elif len(sys.argv) = 2: for i in sys.argv[1:]: _argv = i.split('=') # source server name if _argv[0] == '-s_h': p_s_h = _argv[1] # source server instance name if _argv[0] == '-s_i': if (_argv[1]): p_s_i = _argv[1] # source server instance PORT if _argv[0] == '-s_P': if (_argv[1]): p_s_P = _argv[1] # source database name if _argv[0] == '-s_d': p_s_d = _argv[1] if _argv[0] == '-s_u': p_s_u = _argv[1] if _argv[0] == '-s_p': p_s_p = _argv[1] if _argv[0] == '-t_h': p_t_h = _argv[1] if _argv[0] == '-t_i': if (_argv[1]): p_t_i = _argv[1] if _argv[0] == '-t_P': if (_argv[1]): p_t_P = _argv[1] if _argv[0] == '-t_d': p_t_d = _argv[1] if _argv[0] == '-t_u': p_t_u = _argv[1] if _argv[0] == '-t_p': p_t_p = _argv[1] if _argv[0] == '-f': if (_argv[1]): p_f = _argv[1] # object type if _argv[0] == '-obj_type': if not (_argv[1]): print("-obj_type can not be null ") exit(0) else: p_obj_type = _argv[1] # object name if _argv[0] == '-obj': if (_argv[1]): p_obj = _argv[1] # require para if p_s_h.strip() == "": print("source server host cannot be null") exit(0) if p_s_d.strip() == "": print("source server host database name cannot be null") exit(0) if p_t_h.strip() == "": print("target server host cannot be null") exit(0) if p_t_d.strip() == "": print("target server host database name cannot be null") exit(0) sync = SyncDatabaseObject(s_h=p_s_h, s_i=p_s_i, s_P=p_s_P, s_d=p_s_d, s_u=p_s_u, s_p=p_s_p, s_obj=p_obj, t_h=p_t_h, t_i=p_t_i, t_P=p_t_P, t_d=p_t_d, t_u=p_t_u, t_p=p_t_p, f=p_f) sync.validated_connect(p_s_h, p_s_i, p_s_P, p_s_d, p_s_u, p_s_p) sync.validated_connect(p_t_h, p_t_i, p_t_P, p_t_d, p_t_u, p_t_p) if (p_f.upper() == "Y"): confirm = input("confirm you want to overwrite the target object ") if confirm.upper() != "Y": exit(0) print("-------------------------- sync begin ----------------------------------") print() if (p_obj_type == "tab"): # sync schema sync.sync_schema() # sync table schema sync.sync_table_schema() # sync data sync.sync_table_data() elif (p_obj_type == "sp"): # sync schema sync.sync_schema() # sync sp sync.sync_procudre("p") elif (p_obj_type == "fn"): # sync schema sync.sync_schema() # sync sp sync.sync_procudre("fn") elif (p_obj_type == "tp"): # sync schema sync.sync_schema() # sync sp sync.sync_table_variable() else: print("-obj_type is not validated") print() print("-------------------------- sync finish ----------------------------------")

总结

如上所述是笔者给我们介绍的基于Python的SQL
Server数据库实现指标同步轻量级,希望对我们持有助于,借使我们有其它难题招待给本人留言,我会及时过来大家的!

发表评论

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