题记:上两个星期一直在用SQL2000的DTS做一个数据自动转移备份的程序,结果把这一块的东西又研究了一下。以往也用SQL不过是学习课本上照本宣科的东西,实用就是用网页读数据库,只要安装好数据库能正确连接就好了,也没深入探讨。最近又用的时候,才发现SQL的水真是深啊,一不小心就被一个问题搅的晕头转向。还好,现在咨询发达,可以查帮助文档和网上搜索,因此,这些问题也逐渐解决了。把以前和最近的总结文档整理一下,记录下来,也让其他人遇到一样问题时来搜索我的文章吧!
(一)数据库(一)安装相关—挂起、创建实例失败
(二)数据库(二)连接—数据库连接失败
(三)数据库(三)转移—DTS相关
(四)数据库(四)转移—视图、存储过程、约束和触发器
问题来源:做数据转移时,选择的是在两个SQL数据库之间复制数据,大多数情况下一般的表都能转移,但有时候会有一些莫名奇妙的错误。最后查了很多资料,终于知道是一些表中有数据表的约束、扩展属性、触发器等或者视图、存储过程的相关联系等在复制时会产生的问题。说实话,索引、视图、游标、存储过程、约束和触发器这些部分,每一个拿出来都可以讨论很多,我只是就我在项目中遇到了问题,重点谈一下。
一、系统表的使用
服务器上所有的数据库包括MODULE,MASTER等都含有18个具有相同名称、结构的系统表,如表SYSOBJECTS用于描述数据库中的对象--表、视图、存储过程等,表SYSUSER用于描述数据库的用户,而MASTER数据库另外还有13个单独的全局系统表,如表SYSLOGINS用于保存每个服务器的登录名、口令和配置信息、表SYSDATABASE保存服务器上所有数据库名、所有者、状态及其他信息。数据库中有很多关键信息都存在系统表中,SQL SVR数据库中三张重要的系统表:
sysobjects:在数据库内创建的每个对象(约束、默认值、日志、规则、存储过程等)在表中占一行。
sysindexes:数据库中的每个索引和表在表中各占一行。
syscolumns:每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行。
这三张表用ID(表ID)字段关联。具体的一些参数可以看数据库帮助文档,下面介绍一些简单应用:
--查看表的属性
select * from sysObjects where [Name] = 'section'
--获取所有用户表
select Name from sysobjects where xtype='u' and status>=0
--查看表的字段
select * from sysColumns c where c.id=object_id('section')
--查看用户
select * From sysusers where status<>0
--查看谁引用了bbs_hits表(包括视图、存储过程、函数)
Select distinct object_name(d.id) as 'program',
o.xtype
from sysdepends d inner join sysobjects o on d.id=o.id
where object_name(depid)='bbs_hits'
--查看与某一个表相关的视图、存储过程、函数
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'
--查看当前数据库中所有存储过程
select name as 存储过程名称 from sysobjects where xtype='P'
其中xtype分别对应:
C = CHECK 约束 D = 默认值或 DEFAULT 约束 F = FOREIGN KEY 约束
FN = 标量函数 IF = 内嵌表函数 K = PRIMARY KEY 或 UNIQUE 约束
L = 日志 P = 存储过程 R = 规则 RF = 复制筛选存储过程 S = 系统表
TF = 表函数 TR = 触发器 U = 用户表 V = 视图 X = 扩展存储过程
二、视图
视图(View)是一种常用的数据库对象,他提供了查看和存取数据的另外一种途径。使用视图不仅可以简化数据操作,还可以提高数据的安全性。具体创建视图我就不多说了,我现在讲讲如何将视图复制转移到另一个数据库。
用DTS的“从源数据库复制表和视图”项时,这里的复制视图,是复制视图的结果而不是定义。复制最后在目标数据库表格中生成了以视图名+VIEW的数据表。当然,用数据库备份还原或者分离附件也可以将视图整体复制成功,但我这里说的是复制部分视图和表。
因此,复制部分表和视图结构可以有两种方式:
一是:DTS中“SQL Server 实例之间传输数据库对象”,这里可以复制视图的定义到目的数据库。但是注意,复制视图时,如果目的表中不存在视图定义中相关的表,这要选择“包括相关对象”,将视图引用的基本表也复制过去。但是极端情况下,有时会出错。主要就是A、目的数据库存在视图引用的表,但表中主键、外键、触发器或约束等不一样。B、视图A和视图B相互相关,这样复制A前要复制B,复制B前又要复制A,都不能复制出错。遇到这种情况就要一一针对问题解决了,有时需要分步执行。
二是:生成脚本,然后在查询器中执行就行了。具体:1.右键数据库-》所有任务-》生成SQL脚本-》点“全部显示”-》 勾选相应的表、视图、存储过程。在“设置格式”和“选项”中还可以进一步进行相关设置,以保证复制无误和数据表格定义的完整性。这个和DTS中一样,遇到相同的问题时也会出错。不过因为是直接用脚本,出错时很容易发现问题在哪里,可针对性解决。缺点是:麻烦,要手工解决问题。
其实,仔细研究DTS,你就可以发现,DTS也是执行了相应的脚本,然后开始复制数据的。因此,如果DTS出错,又不知道为何出错时。我就执行脚本语言,检查错误原因,非常有效。
三、存储过程
存储过程式存放在服务器上的Transact-SQL语句的预编译集合,它以一个名称存储在数据库中,并且是作为一个单元处理的。存储过程在第一次执行时进行语法检查和编译,编译好的版本存储在高速缓存中,用于后续调用。存储过程可以由应用程序通过一个调用来执行,而且允许用户声明变量和有条件执行,允许包含程序流、逻辑以及对数据库的查询,可以接受输入参数和输出参数,还可以返回单个或多个集以及返回值。存储过程使得对数据库的管理工作变得更加容易。
这就不用说了,我们写程序时,为了实现程序可移植性、加快执行速度、减少网络流量,一般都会使用存储过程。这样可以修改存储过程而不会直接影响程序,方便快捷。
四、触发器
触发器是一种特殊类型的存储过程,当试图修改它所要保护的数据时,触发器就被请求。当数据传输备份时,如果其他人在这些海量数据中某个表设置了一个触发器的定义,一旦触发,数据传输就会报错。我当时就是这样,百思不得其解。最后我发现部分表可以转移成果,部分不行。我就用二分法,不断缩小不能成果传送的表,最后锁定了一个表,一查,果然其设置了触发器。因此,传输表时,要注意这些表。
比如,要常看所有定义了存储过程的表可以用下面的语句:
select name from sysobjects
where id in (select parent_obj from sysobjects where xtype='TR' and status>=0)
五、数据完整性
进行数据库的转移备份时,最怕出现的东西就是数据因为完整性原因备份失败。 声明数据完整性可以使用约束、默认和规则实现。这些都是在转移过程中经常遇到的完整性约束,如果要保证把这些规则也备份,传输时就要多加小心,了解其规定。
SQL Server 2000支持下列五类约束:(1)DEFAULT约束(默认约束):当向数据库表中插入数据时,如果没有明确的提供输入值时,SQL S自动为该列输入指定值。(2)CHECK约束(检查约束):通过逻辑表达式判断限制插入到列中的值。(3)PRIMARY KEY约束(主键约束):不允许数据库表在指定列上具有相同的值,且不允许有空值。(4)FOREIGN KEY约束(外键约束):定义数据库表中指定列上插入或更新的数值必须在另一张被参照表中的特定列上存在。(5)UNIQUE约束(惟一约束):不允许数据库表在指定列上具有相同的值,但允许有空值。约束也被分为列约束和表约束两类。列约束是指只对某一列起作用的约束。当一个约束中包含了数据库表中一个以上的列时,称为表约束。
可以通过使用系统存储过程sp_help,sp_helptext,sp_helpconstraint来查看约束的相关信息。具体命令的语法如下: EXEC sp_help (sp_helptext,sp_helpconstraint) <constraint_name>其中:sonstraint_name为需要查看的约束的名称。
或者使用规划视图,如使用系统规划视图check_constraints查看数据库tsinghua上存在的所有约束的相关信息。具体命令如下:SELECT * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS go
与在约束中介绍的DEFAULT约束一样,使用默认也可以实现当用户在向数据库表中插入一行数据时,如果没有明确给出某列的输入值时,则由SQL Server自动为该列输入默认值。但与DEFAULT约束不同的是,默认是一种数据库对象,在数据库中只需定义一次后,就可以被一次或多次应用于任意表中的一列或多列,还可以用于用户定义的数据类型。
通过使用规则,用户要可以指定插入数据库表上列中的有效值,从而确保数据在指定的取值范围内,并与特定的模式或特定数据库表中实体匹配。规则也是一种数据库对象。因此和默认一样在数据库中只需定义一次,就可以被一次或多次应用于任意表中的一列或多列,也可以用于用户定义的数据类型。
同触发器类似,我们可以结合系统表来仔细常看数据库中所有定义了完整性约束的表,具体语句就不写了。
至此,我的数据库转移相关的博客就写完了。当然,这些都是很基础的东西,如果要做一个完整的项目,还需要多常看SQl的帮助文档——真是一个好东西啊!