三、连接查询

  通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。

  在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,尔后通过连接进行查询。

  连接可以在Select 语句的FROM子句或Where子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与Where子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。

  SQL-92标准所定义的FROM子句的连接语法格式为:

  FROM join_table join_type join_table
  [ON (join_condition)]

  其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自连接。

  join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。

  交叉连接(CROSS JOIN)没有Where 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

  连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成。

  无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接。例如:

  Select p1.pub_id,p2.pub_id,p1.pr_info
  FROM pub_info AS p1 INNER JOIN pub_info AS p2
  ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)

  (一)内连接
  内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分三种:
  1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。
  2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
  3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。
  例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:

  Select *
  FROM authors AS a INNER JOIN publishers AS p
  ON a.city=p.city
  又如使用自然连接,在选择列表中删除authors 和publishers 表中重复列(city和state):
  Select a.*,p.pub_id,p.pub_name,p.country
  FROM authors AS a INNER JOIN publishers AS p
  ON a.city=p.city

  (二)外连接
  内连接时,返回查询结果集合中的仅是符合查询条件( Where 搜索条件或 HAVING 条件)和连接条件的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。如下面使用左外连接将论坛内容和作者信息连接起来:

  Select a.*,b.* FROM luntan LEFT JOIN usertable as b
  ON a.username=b.username

  下面使用全外连接将city表中的所有作者以及user表中的所有作者,以及他们所在的城市:

  Select a.*,b.*
  FROM city as a FULL OUTER JOIN user as b
  ON a.username=b.username

  (三)交叉连接
  交叉连接不带Where 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等于6*8=48行。
   Select type,pub_name
  FROM titles CROSS JOIN publishers
  ORDER BY type

http://blog.chinaunix.net/u/22313/showart.php?id=214419


5 ? MS SQL 2005 安全设置
2006-02-02T19:07:54+08:00 | rxl

拿到MS SQL 2005还没有一天,总的来说,MS SQL 2005的安全性比SQL 2000要强上不少,不过默认设置还是有和原来一样的漏洞,下面我们来修改一下默认设置。

1、安装MSSQL时使用混合模式,当然SA密码最好不能为空,在SQL2005中,可以对SA这个超级用户名进行修改或删除。
use master
Alter LOGIN [sa] WITH NAME=[zxs] /*修改SA帐号*/
sp_password '111111','123456','sa' /*修改SA密码*/
使用以上命令可修改SA帐号,也可进行图形化的修改
使用安全的帐号策略。对SA或等同用户进行最强的保护,当然,包括使用一个非常强壮的密码,如下图

这里可以看到SQL 2005比SQL 2000 增强的地方了。

2、SQL的认证有Windows身份认证和混合身份认证。在2005中,登陆SQL可以使用indows身份认证和混合身份认证方便,如果不希望系统管理员接触数据库的话,可以在安全性==登录名是把系统帐号“BUILTIN\Administrators”删除。当然,还有别的多余的帐号也可一同禁止,只需要在帐号==属性==状态中把是否允许连接到数据库引擎改为拒绝,还有登录改为禁用即可,不过这样的坏处就是当你忘了SA的密码时,我也没办法帮你啦。

也可用命令sp_change_users_login 'report' 搜索一下独立的帐户再删除

3、管理扩展存储过程
删除不必要的存储过程,因为有些存储过程能很容易地被人利用起来提升权限或进行破坏。
如果你不需要扩展存储过程xp_cmdshell请把它去掉。xp_cmdshell根本就是一个大后门。

如果不需要请丢弃OLE自动存储过程(会造成管理器中的某些特征不能使用),这些过程包括如下:
sp_OACreate sp_OADestroy sp_OAGetErrorInfo sp_OAGetProperty
sp_OAMethod sp_OASetProperty sp_OAStop
去掉不需要的注册表访问的存储过程,注册表存储过程甚至能够读出操作系统管理员的密码来,如下:
xp_regaddmultistring xp_regdeletekey xp_regdeletevalue xp_regenumvalues
xp_regread xp_regremovemultistring xp_regwrite
还有一些其他的扩展存储过程,你也最好检查检查。
在处理存储过程的时候,请确认一下,避免造成对数据库或应用程序的伤害。运行以下SQL语句可删除所有危险的SP。

Drop PROCEDURE sp_makewebtask
exec master..sp_dropextendedproc xp_cmdshell /*命令行*/
exec master..sp_dropextendedproc xp_dirtree /*可以展开你需要了解的目录,获得所有目录深度*/
exec master..sp_dropextendedproc xp_fileexist /*用来确定一个文件是否存在*/
exec master..sp_dropextendedproc xp_getnetname /*可以获得服务器名称*/
exec master..sp_dropextendedproc xp_terminate_process
exec master..sp_dropextendedproc sp_oamethod
exec master..sp_dropextendedproc sp_oacreate
exec master..sp_dropextendedproc xp_regaddmultistring
exec master..sp_dropextendedproc xp_regdeletekey
exec master..sp_dropextendedproc xp_regdeletevalue
exec master..sp_dropextendedproc xp_regenumkeys
exec master..sp_dropextendedproc xp_regenumvalues
exec master..sp_dropextendedproc sp_add_job
exec master..sp_dropextendedproc sp_addtask
exec master..sp_dropextendedproc xp_regread
exec master..sp_dropextendedproc xp_regwrite
exec master..sp_dropextendedproc xp_readwebtask
exec master..sp_dropextendedproc xp_makewebtask
exec master..sp_dropextendedproc xp_regremovemultistring
exec master..sp_dropextendedproc sp_OACreate
Drop PROCEDURE sp_addextendedproc

5、SQL Server 2005本身就具有加密功能,完全集成了一个密钥管理架构。不过,最好远程网络连接时使用SSL来加密协议,这就需要一个证书来支持。这里搜索一下就会有很多这方面的说明,就不多说了。

6、使用IPSec策略阻止所有地址访问本机的TCP1433与UDP1434端口,也可对TCP1433端口进行修改,但是在SQL2005中,可以使用TCP动态端口,(在SQL Server Configuration Manager的SQL 2005网络配置中)如下图


这是SQL帮助中的说明
如果某个 SQL Server 实例已配置为侦听动态端口,则在启动时,该实例将检查操作系统中的可用端口,并为该端口打开一个端点。传入连接必须指定要连接的端口号。由于每次启动 SQL Server 时端口号都可能会改变,因此 SQL Server 提供 SQL Server 浏览器服务器,来监视端口并将传入连接指向该实例的当前端口。
也可对每个IP进行侦听


这是SQL帮助中的说明
指定 SQL Server 是否侦听所有绑定到计算机网卡的 IP 地址。如果设置为“否”,则使用每个 IP 地址各自的属性对话框对各个 IP 地址进行配置。如果设置为“是”,则 IPAll 属性框的设置将应用于所有 IP 地址。默认值为“是”。

当然你也可以下面的SQL Native Client 配置中新建一别名来指定你的SQL服务器和端口,也可在服务器属性==连接==远程服务器链接==把允许远程链接到本服务器的勾去掉
关闭远程链接命令行为
EXEC sys.sp_configure N'remote access', N'0'

8、对远程网络连接进行IP限制,SQL Server 2005如同SQL 2000一样没有提供网络连接的安全解决办法,但是Windows 2K以上系统了提供了IPSec策略。对远程网络连接的IP进行限制,只保证需要的IP能够访问,拒绝其他 IP进行的端口连接,把安全威胁降到最低。

9、在服务器的属性安全中,启用登录审核中的失败与成功登陆,启用C2审核跟踪,C2是一个政府安全等级,它保证系统能够保护资源并具有足够的审核能力。C2模式允许我们监视对所有数据库实体的所有访问企图。如图


启用C2审核的命令为
EXEC sys.sp_configure N'c2 audit mode', N'1'

以上的方法不是很完整,因为时间关系以后再慢慢研究。

6 ? SQL Server 2000 (SP4)笔记整理(三):触发器
2006-01-08T09:52:37+08:00 | rxl

/*
建立虚拟测试环境,包含:表[卷烟库存表],表[卷烟销售表]。
请大家注意跟踪这两个表的数据,体会触发器到底执行了什么业务逻辑,对数据有什么影响。
为了能更清晰的表述触发器的作用,表结构存在数据冗余,且不符合第三范式,这里特此说明。
*/

USE Master
GO

IF EXISTS (Select NAME FROM SYSOBJECTS Where XTYPE = 'U' AND NAME = '卷烟库存表')
    Drop TABLE 卷烟库存表
GO
IF EXISTS (Select NAME FROM SYSOBJECTS Where XTYPE = 'U' AND NAME = '卷烟销售表')
    Drop TABLE 卷烟销售表
GO

--业务规则:销售金额 = 销售数量 * 销售单价 业务规则。

Create TABLE 卷烟销售表
(
    卷烟品牌        VARCHAR(40) PRIMARY KEY NOT NULL,
    购货商          VARCHAR(40) NULL,
    销售数量        INT NULL,
    销售单价        MONEY NULL,
    销售金额        MONEY NULL
)
GO

--业务规则:库存金额 = 库存数量 * 库存单价 业务规则。

Create TABLE 卷烟库存表
(
    卷烟品牌        VARCHAR(40) PRIMARY KEY NOT NULL,
    库存数量        INT NULL,
    库存单价        MONEY NULL,
    库存金额        MONEY NULL
)
GO

--创建触发器,示例1

/*
创建触发器[T_Insert_卷烟库存表],这个触发器较简单。
说明:      每当[卷烟库存表]发生 Insert 动作,则引发该触发器。
触发器功能:    强制执行业务规则,保证插入的数据中,库存金额 = 库存数量 * 库存单价。
注意:      [InsertED]、[DeleteD]为系统表,不可创建、修改、删除,但可以调用。
重要:      这两个系统表的结构同插入数据的表的结构。
*/
IF EXISTS (Select NAME FROM SYSOBJECTS Where XTYPE = 'TR' AND NAME = 'T_Insert_卷烟库存表')
    Drop TRIGGER T_Insert_卷烟库存表
GO

Create TRIGGER T_Insert_卷烟库存表
ON 卷烟库存表
FOR Insert
AS
--提交事务处理
BEGIN TRANSACTION
    --强制执行下列语句,保证业务规则
    Update 卷烟库存表
    SET 库存金额 = 库存数量 * 库存单价
    Where 卷烟品牌 IN (Select 卷烟品牌 from InsertED)
COMMIT TRANSACTION
GO

/*
针对[卷烟库存表],插入测试数据:
注意,第一条数据(红塔山新势力)中的数据符合业务规则,
第二条数据(红塔山人为峰)中,[库存金额]空,不符合业务规则,
第三条数据(云南映像)中,[库存金额]不等于[库存数量]乘以[库存单价],不符合业务规则。
第四条数据库存数量为0。
请注意在插入数据后,检查[卷烟库存表]中的数据是否 库存金额 = 库存数量 * 库存单价。
*/

Insert INTO 卷烟库存表(卷烟品牌,库存数量,库存单价,库存金额)
    Select '红塔山新势力',100,12,1200 UNION ALL
    Select '红塔山人为峰',100,22,NULL UNION ALL
    Select '云南映像',100,60,500      UNION ALL
    Select '玉溪',0,30,0
GO

--查询数据

Select * FROM 卷烟库存表
GO
/*

结果集

RecordId 卷烟品牌       库存数量 库存单价 库存金额
-------- ------------ -------- ------- ---------
1         红塔山新势力   100       12.0000 1200.0000
2         红塔山人为峰   100       22.0000 2200.0000
3         云南映像       100       60.0000 6000.0000
4         玉溪           0         30.0000 .0000

(所影响的行数为 4 行)

*/


--触发器示例2

/*
创建触发器[T_Insert_卷烟销售表],该触发器较复杂。
说明:       每当[卷烟库存表]发生 Insert 动作,则引发该触发器。
触发器功能:    实现业务规则。
业务规则:   如果销售的卷烟品牌不存在库存或者库存为零,则返回错误。
            否则则自动减少[卷烟库存表]中对应品牌卷烟的库存数量和库存金额。
*/
IF EXISTS (Select NAME FROM SYSOBJECTS Where XTYPE = 'TR' AND NAME = 'T_Insert_卷烟销售表')
    Drop TRIGGER T_Insert_卷烟销售表
GO

Create TRIGGER T_Insert_卷烟销售表
ON 卷烟销售表
FOR Insert
AS
BEGIN TRANSACTION
    --检查数据的合法性:销售的卷烟是否有库存,或者库存是否大于零
    IF NOT EXISTS (
        Select 库存数量
        FROM 卷烟库存表
        Where 卷烟品牌 IN (Select 卷烟品牌 FROM InsertED)
    )
        BEGIN
            --返回错误提示
            RAISERROR('错误!该卷烟不存在库存,不能销售。',16,1)
            --回滚事务
            ROLLBACK
            RETURN
        END

    IF EXISTS (
        Select 库存数量
        FROM 卷烟库存表
        Where 卷烟品牌 IN (Select 卷烟品牌 FROM InsertED) AND
        库存数量 <= 0          
    )
        BEGIN
            --返回错误提示
            RAISERROR('错误!该卷烟库存小于等于0,不能销售。',16,1)
            --回滚事务
            ROLLBACK
            RETURN
        END
   
    --对合法的数据进行处理

    --强制执行下列语句,保证业务规则
    Update 卷烟销售表
    SET 销售金额 = 销售数量 * 销售单价
    Where 卷烟品牌 IN (Select 卷烟品牌 FROM InsertED)

    DECLARE @卷烟品牌 VARCHAR(40)
    SET @卷烟品牌 = (Select 卷烟品牌 FROM InsertED)

    DECLARE @销售数量 MONEY
    SET @销售数量 = (Select 销售数量 FROM InsertED)

    Update 卷烟库存表
    SET 库存数量 = 库存数量 - @销售数量,
        库存金额 = (库存数量 - @销售数量)*库存单价
    Where 卷烟品牌 = @卷烟品牌
COMMIT TRANSACTION
GO

--请大家自行跟踪[卷烟库存表]和[卷烟销售表]的数据变化。
--针对[卷烟销售表],插入第一条测试数据,该数据是正常的。

Insert INTO 卷烟销售表(卷烟品牌,购货商,销售数量,销售单价,销售金额)
    Select '红塔山新势力','某购货商',10,12,1200
GO

--针对[卷烟销售表],插入第二条测试数据,该数据 销售金额 不等于 销售单价 * 销售数量。
--触发器将自动更正数据,使 销售金额 等于 销售单价 * 销售数量。

Insert INTO 卷烟销售表(卷烟品牌,购货商,销售数量,销售单价,销售金额)
    Select '红塔山人为峰','某购货商',10,22,2000
GO

--针对[卷烟销售表],插入第三条测试数据,该数据中的卷烟品牌在 卷烟库存表 中找不到对应。
--触发器将报错。

Insert INTO 卷烟销售表(卷烟品牌,购货商,销售数量,销售单价,销售金额)
    Select '红河V8','某购货商',10,60,600
GO

/*
结果集
服务器: 消息 50000,级别 16,状态 1,过程 T_Insert_卷烟销售表,行 15
错误!该卷烟不存在库存,不能销售。
*/

--针对[卷烟销售表],插入第三条测试数据,该数据中的卷烟品牌在 卷烟库存表 中库存为0。
--触发器将报错。

Insert INTO 卷烟销售表(卷烟品牌,购货商,销售数量,销售单价,销售金额)
    Select '玉溪','某购货商',10,30,300
GO

/*
结果集
服务器: 消息 50000,级别 16,状态 1,过程 T_Insert_卷烟销售表,行 29
错误!该卷烟库存小于等于0,不能销售。
*/
--查询数据
Select * FROM 卷烟库存表

Select * FROM 卷烟销售表
GO

/*
补充:
1、本示例主要通过一个简单的业务规则实现来进行触发器使用的说明,具体的要根据需要灵活处理;
2、关于触发器要理解并运用好 InsertED ,DeleteD 两个系统表;
3、本示例创建的触发器都是 FOR Insert ,具体的语法可参考:

    Trigger语法

    Create TRIGGER trigger_name
    ON { table | view }
    [ WITH ENCRYPTION ] --用于加密触发器
    {
        { { FOR | AFTER | INSTEAD OF } { [ Insert ] [ , ] [ Update ] }
            [ WITH APPEND ]
            [ NOT FOR REPLICATION ]
            AS
            [ { IF Update ( column )
                [ { AND | OR } Update ( column ) ]
                    [ ...n ]
            | IF ( COLUMNS_UpdateD ( ) { bitwise_operator } updated_bitmask )
                    { comparison_operator } column_bitmask [ ...n ]
            } ]
            sql_statement [ ...n ]
        }
    }

4、关于触发器,还应该注意
(1)、Delete 触发器不能捕获 TRUNCATE TABLE 语句。
(2)、触发器中不允许以下 Transact-SQL 语句:
        Alter DATABASE Create DATABASE DISK INIT
        DISK RESIZE Drop DATABASE LOAD DATABASE
        LOAD LOG RECONFIGURE RESTORE DATABASE
        RESTORE LOG
(3)、触发器最多可以嵌套 32 层。

*/

--修改触发器
--实质上,是将 Create TRIGGER ... 修改为 Alter TRIGGER ...即可。

--删除触发器
Drop TRIGGER xxx
GO

--删除测试环境
Drop TABLE 卷烟库存表
GO
Drop TABLE 卷烟销售表
GO
Drop TRIGGER T_Insert_卷烟库存表
GO
Drop TRIGGER T_Insert_卷烟销售表
GO


7 ? SQL Server 2000 (SP4)笔记整理(二):数据库表
2006-01-08T09:51:50+08:00 | rxl

USE Master
GO

--检查是否存在测试表,若存在,则删除之
IF EXISTS (Select NAME FROM SYSOBJECTS Where XTYPE = 'U' AND NAME = 'MyTestTable1')
    Drop TABLE MyTestTable1
GO

Create TABLE MyTestTable1
(
    编号        INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    姓名        CHAR(8),
    别名        VARCHAR(8),
    性别        CHAR(2) DEFAULT ('男'),
    年龄        INT CHECK(年龄>0 AND 年龄<100),
)ON [PRIMARY]
GO

--插入数据:

/*
下面的语句将不能执行,因为 [编号] 列为系统自动自增列。

Insert INTO MyTestTable1(编号,姓名,别名,性别,年龄)
    VALUES (1,'彭建军','彭建军','男',25)
GO

在当 IDENTITY_Insert 设置为 OFF 时,不能向表 'MyTestTable1' 中的标识列插入显式值。

*/

--正确的语句,方法一
Insert INTO MyTestTable1(姓名,别名,性别,年龄)
    VALUES ('彭建军','彭建军','男',25)
GO
--方法二:
Insert INTO MyTestTable1(姓名,别名,性别,年龄)
    Select '老转','老转','男',30 UNION ALL
    Select '钱妮','妮子','女',28
GO

--查询数据(注意编号的自增性)

Select * FROM MyTestTable1
GO

/*

结果集

编号          姓名       别名       性别   年龄         
----------- -------- -------- ---- -----------
1           彭建军      彭建军      男    25
2           老转        老转        男    30
3           钱妮        妮子        女    28

*/

--验证 默认值,不插入[性别]的值,则系统取默认值
Insert INTO MyTestTable1(姓名,别名,年龄)
    Select '潘颖','梨窝浅笑',25
GO

--查询
Select * FROM MyTestTable1 Where 姓名 = '潘颖'
GO

/*

结果集
编号          姓名       别名       性别   年龄         
----------- -------- -------- ---- -----------
4           潘颖       梨窝浅笑     男    25

*/

--验证 CHECK,插入[年龄]的值超过100,则系统报错
Insert INTO MyTestTable1(姓名,别名,性别,年龄)
    Select '蛋蛋','蛋蛋','女',120
GO

/*

结果集

Insert 语句与 COLUMN CHECK 约束 'CK__MyTestTable1__年龄__30B91D22' 冲突。该冲突发生于数据库 'master',表 'MyTestTable1', column '年龄'。
语句已终止。

*/

--修改表

--增加列
Alter Table MyTestTable1
ADD 备注    VARCHAR(50)
GO

--修改列定义
Alter Table MyTestTable1
Alter COLUMN 备注 VARCHAR(100)
GO

--清空表的数据

--方法一(删除的数据将记入日志)
Delete FROM MyTestTable1
GO

--如果是删除特定的行,则类似于 Delete FROM MyTestTable1 Where 编号 = 1

--方法二(删除的数据不记入日志,执行效率高)
TRUNCATE TABLE MyTestTable1
GO

--删除表(谨慎使用!)
Drop TABLE MyTestTable1
GO


8 ? SQL Server 2000 (SP4)笔记整理(一):数据库
2006-01-08T09:50:39+08:00 | rxl

--数据库创建示例1

--首先必须在C盘下建立[DataBase]文件夹

USE Master
GO

--检查是否存在测试数据库,若存在,则删除之
IF EXISTS (Select NAME FROM SYSDATABASES Where NAME = 'MyDB')
    Drop DATABASE MyDB
GO

Create DATABASE MyDB
ON
--数据文件
(
    NAME = MyDB_dat,
    FILENAME = 'C:\DataBase\MyDB_dat.mdf',
    SIZE = 10,--默认值为 MB
    MAXSIZE = 50,
    FILEGROWTH = 5
)
--日志文件
LOG ON
(
    NAME = MyDB_log,
    FILENAME = 'C:\DataBase\MyDB_log.ldf',
    SIZE = 1MB,
    MAXSIZE = 25MB,
    FILEGROWTH = 1MB
)
GO

--数据库创建示例2

USE Master
GO

IF EXISTS (Select NAME FROM SYSDATABASES Where NAME = 'MyDB')
    Drop DATABASE MyDB
GO

USE Master
GO

Create DATABASE MyDB
ON
--主数据文件
(
    NAME = MyDB_dat1,
    FILENAME = 'C:\DataBase\MyDB_dat1.mdf',
    SIZE = 10,--默认值为 MB
    MAXSIZE = 50,
    FILEGROWTH = 5
),
--次要数据文件
(
    NAME = MyDB_dat2,
    FILENAME = 'C:\DataBase\MyDB_dat2.ndf',
    SIZE = 10,--默认值为 MB
    MAXSIZE = 50,
    FILEGROWTH = 5
)
LOG ON
--主日志
(
    NAME = MyDB_log1,
    FILENAME = 'C:\DataBase\MyDB_log1.ldf',
    SIZE = 1MB,
    MAXSIZE = 25MB,
    FILEGROWTH = 1MB
),
--次要日志
(
    NAME = MyDB_log2,
    FILENAME = 'C:\DataBase\MyDB_log2.ldf',
    SIZE = 1MB,
    MAXSIZE = 25MB,
    FILEGROWTH = 1MB
)
GO

--删除数据库(请谨慎使用!)

Drop DATABASE MyDB
GO

--分离数据库

EXEC sp_detach_db 'MyDB'
GO

--附加数据库

Create DATABASE MyDB
ON PRIMARY
(
    FILENAME = 'C:\DataBase\MyDB_dat1.mdf'
)
FOR ATTACH
GO

--修改数据库

--增加数据库数据文件
Alter DATABASE MyDB
ADD FILE
(
    NAME = MyDB_dat3,
    FILENAME = 'C:\DataBase\MyDB_dat3.ndf',
    SIZE = 10,--默认值为 MB
    MAXSIZE = 50,
    FILEGROWTH = 5
)
GO

--清除数据库数据文件
Alter DATABASE MyDB
REMOVE FILE MyDB_dat3
GO

--修改数据库配置参数
Alter DATABASE MyDB
MODIFY FILE
(
    NAME = 'MyDB_dat1',
    SIZE = 20MB
)
GO

--查询数据库信息

USE Master
GO

Select * FROM SYSDATABASES

--备份数据库

BACKUP DATABASE MyDB
    TO DISK = 'C:\DataBase\MyDB_BackUp.BAK'
GO

--利用备份还原数据库
IF EXISTS (Select NAME FROM SYSDATABASES Where NAME = 'MyDB')
    Drop DATABASE MyDB
GO

RESTORE FILELISTONLY
    FROM DISK = 'C:\DataBase\MyDB_BackUp.BAK'
RESTORE DATABASE MyDB
    FROM DISK = 'C:\DataBase\MyDB_BackUp.BAK'
    WITH
        MOVE 'MyDB_dat' TO 'C:\DataBase\MyDB_dat.mdf',
        MOVE 'MyDB_log' TO 'C:\DataBase\MyDB_log.ldf'
GO

posted on 2008-07-01 13:29  yhb199  阅读(634)  评论(0编辑  收藏  举报