“甘蔗麻烦砍一下”通过精心收集,向本站投稿了9篇SQL Server 之日志传送功能 设定数据库教程,下面是小编整理后的SQL Server 之日志传送功能 设定数据库教程,欢迎大家阅读分享借鉴,欢迎大家分享。

篇1:SQL Server 之日志传送功能 设定数据库教程
server
SQL Server 2000之日志传送功能 - 设定(1)
日志传送功能可自动复制数据库的交易日志文件,并回存到备援服务器 (standby server) 的另外一个数据库,因此可大幅提高SQL Server数据库之可用性。因为备援数据库完整地接收来源数据库的异动情况,所以它就是一份来源数据库的复本 - 差别仅在于资料复制与加载过程所产生的时间差。然而,当主要服务器停摆时,您就可以将备援服务器更改为新的主要服务器。如果原来的主要服务器可重新上线使用,那么您可以将其设定为新的备援服务器 - 事实上就是对调两台服务器的角色。
在SQL Server 2000企业版或开发版之中,Microsoft在Enterprise Manager内提供了一项日志传送(Log Shipping)的功能 - 为数据库维护计划精灵的其中一部份。在使用之前的SQL Server时,您需要自行建立日志传送系统。
设定日志传送
主要服务器(primary server) 即是实际处理资料的正式服务器;此服务器内拥有来源数据库。次要服务器(secondary server)上存放目的数据库,用来复制与回存来源数据库的交易日志文件。监控服务器(monitor server)用来监控主要服务器与次要服务器。与SQL Server 7.0不同的是(SQL Server 7.0是在次要服务器上监控日志传送动作),SQL Server 2000使用Enterprise Manager的日志传送监控工具来监控每一组传送中的日志资料。Microsoft建议您在另外一台监控用服务器安装这个工具程序。
您可以利用Enterprise Manager的数据库维护计划精灵设定SQL Server 2000的日志传送。但是在您激活精灵之前,您必须先进行某些准备工作。一开始请先遵循下列步骤:
1.决定一组要设定日志传送的服务器(即日志传送过程之中,主要服务器与次要服务器为何)。
2. 选择一台监控服务器。最好不同于主要服务器或次要服务器。
3. 设定所有服务器之安全性。您用来设定日志传送的Windows帐号必须拥有所有服务器上SQL Server系统管理者(sa)的权限。
4. 在主要/次要服务器上建立分享资料夹。首先,将来源数据库交易日志文件所在的目录设定为分享目录。接着在次要服务器上,将您打算回存交易日志文件的目录也分享出来。为了清楚辨别各分享目录,请在分享名称内注明服务器与数据库之名称。如果分享目录名称已存在,您可能需要从分享目录中删除或是搬移其它档案,特别是旧的日志备份文件。然后再将这些分享目录的权限开放给每一台服务器上SQL Agent所使用的Windows帐号。
5. 决定如何建立并初始化目的地数据库。您可以在日志传送设定过程就先建立与初始同步化目的地数据库,否则您必须手动进行初始数据库之回存动作。
6. 在Enterprise Manager注册此三台服务器(即主要、次要与监控服务器)。
在您完成这些准备动作时,您就可以准备激活数据库维护计划精灵来设定日志传送。您可以先检视日志传送过程的五个连续步骤,如图1所示:
图1:SQL Server 2000日志传送的设定步骤。
前两个为选择性(optional)步骤。如果您尚未同步化来源与目的数据库,则步骤1会为您先备份来源数据库,然后执行同步化动作。在步骤2时,精灵会将备份文件复制到次要服务器,并回存到目的地数据库。
精灵一定会执行其余三项步骤。在步骤3时,精灵将在主要服务器上建立一个SQL Agent工作(job)。此工作将会周期性地把交易日志文件内容备份到磁盘档案内。精灵也会在次要服务器上建立一个传送日志的数据库维护计划;此计画包含两个SQL Agent工作:一个是将交易日志文件复制到次要服务器(步骤4),另一个则是将交易日志文件回存到目的数据库(步骤5)。这些步骤将建立一组日志传送服务器(互相有日志传送关系的两个数据库)。如果您想要额外提供容错功能或是设定一台报表服务器,那么您可以将主要服务器与另外一台次要服务器组合在一起,再设定一组日志传送配对服务器。
准备工作
1. 准备 Primary Server (以下为Ztao-1) 及SecondaryServer (以下为IntronTest)
2. 将要作 Log Shipping 的数据库(以下为IntronERP)之还原模型(Recovery Model)设定为完整(FULL)。
3. 将两台计算机的SQL Server服务账号加入Administrator群组
4. 建立Primary Server 备份Log的数据夹
a. 建立C:\Logfile,以存放Primary Server数据库Transaction Log的备份
b. 将C:\Logfile作数据分享,分享目录的权限开放给SQL Agent所使用的Windows帐号。
5. 建立SecondaryServer 还原的数据夹(在SecondaryServer)
a. 建立C:\Shippedlog数据夹以存放从Primary Server传送过来的Transaction log 的备份
b. 建立 C:\Logfile数据夹,当角色交换后,可存放新Primary Server的数据库Transaction Log
c. 将C:\Logfile数据夹作资源共享,分享目录的权限开放给SQL Agent所使用的Windows帐号。
6. 在Primary Server中,新增SecondaryServer的注册信息
if exists(
select * from sysobjects
where name='pr_backup_db' and xtype='p'
)
begin
drop proc pr_backup_db
end
go
/*备份数据库*/
create proc pr_backup_db
@flag varchar(10) out,
@backup_db_name varchar(128),
@filename varchar(1000) --路径+文件名字
as
declare @sql nvarchar(4000),@par nvarchar(1000)
select @par='@filename varchar(1000)'
select @sql='BACKUP DATABASE'+@backup_db_name+'todisk=@filenamewith init'
execute sp_executesql @sql,@par,@filename
select @flag='ok'
go
if exists(
select * from sysobjects
where name='fn_GetFilePath' and xtype='fn'
)
begin
drop function fn_GetFilePath
end
go
/*创建函数,得到文件得路径*/
create function fn_GetFilePath(@filename nvarchar(260))
returns nvarchar(260)
as
begin
declare @file_path nvarchar(260)
declare @filename_reverse nvarchar(260)
select @filename_reverse=reverse(@filename)
select @file_path=substring(@filename,1,len(@filename)+1-charindex('\',@filename_reverse))
return @file_path
end
go
if exists(
select * from sysobjects
where name='pr_restore_db' and xtype='p'
)
begin
drop proc pr_restore_db
end
go
create proc pr_restore_db /*恢复数据库*/
@flag varchar(20) out, /*过程运行的状态标志,是输入参数*/
@restore_db_name nvarchar(128), /*要恢复的数据名字*/
@filename nvarchar(260) /*备份文件存放的路径+备份文件名字*/
as
declare @proc_result tinyint /*返回系统存储过程xp_cmdshell运行结果*/
declare @loop_time smallint /*循环次数*/
declare @max_ids smallint /*@tem表的ids列最大数*/
declare @file_bak_path nvarchar(260) /*原数据库存放路径*/
declare @flag_file bit /*文件存放标志*/
declare @master_path nvarchar(260) /*数据库master文件路径*/
declare @sql nvarchar(4000),@par nvarchar(1000)
declare @sql_sub nvarchar(4000)
declare @sql_cmd nvarchar(4000)
/*
判断参数@filename文件格式合法性,以防止用户输入类似d: 或者 c:\a\ 等非法文件名
参数@filename里面必须有'\'并且不以'\'结尾
*/
if right(@filename,1)'\' and charindex('\',@filename)0
begin
select @sql_cmd='dir'+@filename
EXEC @proc_result = master..xp_cmdshell @sql_cmd,no_output
IF (@proc_result0) /*系统存储过程xp_cmdshell返回代码值:0(成功)或1(失败)*/
begin
select @flag='not exist' /*备份文件不存在*/
return /*退出过程*/
end
/*创建临时表,保存由备份集内包含的数据库和日志文件列表组成的结果集*/
create table #tem(
LogicalName nvarchar(128), /*文件的逻辑名称*/
PhysicalName nvarchar(260) , /*文件的物理名称或操作系统名称*/
Type char(1), /*数据文件 (D) 或日志文件 (L)*/
FileGroupName nvarchar(128), /*包含文件的文件组名称*/
[Size] numeric(20,0), /*当前大小(以字节为单位)*/
[MaxSize] numeric(20,0) /*允许的最大大小(以字节为单位)*/
)
/*
创建表变量,表结构与临时表基本一样
就是多了两列,
列ids(自增编号列),
列file_path,存放文件的路径
*/
declare @tem table(
ids smallint identity, /*自增编号列*/
LogicalName nvarchar(128),
PhysicalName nvarchar(260),
File_path nvarchar(260),
Type char(1),
FileGroupName nvarchar(128)
)
insert into #tem
execute('restore filelistonly fromdisk='''+@filename+'''')
/*将临时表导入表变量中,并且计算出相应得路径*/
insert into @tem(LogicalName,PhysicalName,File_path,Type,FileGroupName)
select LogicalName,PhysicalName,dbo.fn_GetFilePath(PhysicalName),Type,FileGroupName
from #tem
if @@rowcount>0
begin
drop table #tem
end
select @loop_time=1
select @max_ids=max(ids) /*@tem表的ids列最大数*/
from @tem
while @loop_time<=@max_ids
begin
select @file_bak_path=file_path
from @tem whereids=@loop_time
select @sql_cmd='dir'+@file_bak_path
EXEC @proc_result = master..xp_cmdshell @sql_cmd,no_output
/*系统存储过程xp_cmdshell返回代码值:0(成功)或1(失败)*/
IF (@proc_result0)
select @loop_time=@loop_time+1
else
BREAK /*没有找到备份前数据文件原有存放路径,退出循环*/
end
select @master_path=''
if @loop_time>@max_ids
select @flag_file=1 /*备份前数据文件原有存放路径存在*/
else
begin
select @flag_file=0 /*备份前数据文件原有存放路径不存在*/
select @master_path=dbo.fn_GetFilePath(filename)
from master..sysdatabases where name='master'
end
select @sql_sub=''
/*type='d'是数据文件,type='l'是日志文件 */
/*@flag_file=1时新的数据库文件还是存放在原来路径,否则存放路径和master数据库路径一样*/
select @sql_sub=@sql_sub+'move '''+LogicalName+''' to '''
+case type
when 'd' then case @flag_file
when 1 then File_path
else @master_path
end
when 'l' then case @flag_file
when 1 then File_path
else @master_path
end
end
+case type
when 'd' then @restore_db_name+'_'+LogicalName+'_data.mdf'','
when 'l' then @restore_db_name+'_'+LogicalName+'_log.ldf'','
end
from @tem
select @sql='RESTORE DATABASE @db_name FROMDISK=@filenamewith '
select @sql=@sql+@sql_sub+'replace'
select @par='@db_name nvarchar(128),@filename nvarchar(260)'
print @sql
execute sp_executesql @sql,@par,@db_name=@restore_db_name,@filename=@filename
select @flag='ok' /*操作成功*/
end
else
begin
SELECT @flag='file type error' /*参数@filename输入格式错误*/
end
--备份数据库test_database
declare @fl varchar(10)
execute pr_backup_db @fl out,'test_database','c:\test_database.bak'
select @fl
--恢复数据库,输入的参数错误
declare @fl varchar(20)
exec pr_restore_db @fl out,'sa','c:\'
select @fl
--恢复数据库,即创建数据库test_database的复本test_db
declare @fl varchar(20)
exec pr_restore_db @fl out,'test_db','c:\test_database.bak'
select @fl
更改日志传送之组态设定
您可以使用数据库维护计划之【属性】对话盒来更改日志传送相关设定,
在【交易记录文件备份】设定页提供的选项可更改日志传送过程中交易日志文件备份的组态。
【记录传送】设定页显示出您先前在维护计划内设定的日志传送配对服务器;如果您设定了其它组日志传送配对服务器,也会列在此处。本设定页也包含下列选项:新增目的数据库(用以建立新的日志传送配对服务器)、删除既有日志传送配对服务器、编辑目前的日志传送配对服务器之属性,以及移除整个日志传送功能。
当您在【记录传送】设定页之中点选【编辑】时,将开启【编辑目的数据库】对话盒。您可以在对话盒内【一般】设定页检视与修改次要服务器的交易日志文件之目录位置,以及未来做为主要服务器时分享目录之路径。【初始化】设定页则可让您更改复原模式,以及次要服务器上复制与回存之频率。【临界值】页可以设定日志传送之临界周期。
在【超出同步临界值】项目可设定:当日志传送监控程序产生警示讯息之前所能允许的最大时间间隔 (介于最近一次来源数据库交易日志文件备份以及最新的交易日志文件回存动作之间)。您也可以在日志传送监控程序之中设定此参数。【在入时间延迟】、【档案保留期限】以及【历程记录保留期限】则是与次要服务器相关的设定。
注:监控服务器在这些组态选项中扮演相当重要的角色。因为【记录传送】设定页的大部分信息取决于监控服务器,所以一但监控服务器停摆时,您将无法更改日志传送的组态设定值。在监控服务器执行SQL Server 2000 Profiler时,主要服务器会连到监控服务器,然后从日志传送资料表中取得既有的日志传送计划。因此,要改变日志传送计划的设定时,您必须确定在Enterprise Manager内可以连接到监控服务器。
检查与监控日志传送动作
SQL Server 2000的日志传送功能还提供了一项日志传送监控程序,可让您安装在另一 立监控用服务器。
在SQL Server企业版与开发版的msdb数据库中共有七个关于日志传送的资料表:
log_shipping_plans
log_shipping_plan_databases
log_shipping_databases
log_shipping_plan_history
log_shipping_monitor
log_shipping_primaries
log_shipping_secondaries
上述每一个资料表都存在于主要、次要以及监控服务器上。各服务器也会使用某些资料表储存资料,视该服务器在日志传送系统的角色为何。
在主要服务器上检视日志传送动作从Enterprise Manager 里,您可以登入主要服务器,并观察与监控日志传送动作。如果某个数据库已设定要进行日志传送,在数据库【内容】对话盒的【一般】页可得知该数据库的角色(来源数据库;或是目的数据库),也可知道日志传送监控程序是位于那一台服务器上。您可以在Enterprise Manager内SQL Server Agent的【作业】节点,检视日志传送与交易日志文件备份工作所执行的状态与历史纪录。主要服务器只使用msdb数据库的两个日志传送资料表。在log_shipping_databases资料表中,SQL Server新增的每一笔资料将会把数据库维护计划ID以及日志传送来源数据库连结在一起。在log_shipping_monitor资料表中,SQL Server新增的每一笔资料包含了监控服务器的名称,以及登入数据库的方式。
在次要服务器上检视日志传送动作日志传送计划存在于次要服务器。您可在次要服务器监控SQL Agent工作(复制交易日志文件到次要服务器,并回存至目的数据库)。 您也可检视目的数据库的属性对话盒,以决定该数据库在日志传送过程所扮演的角色。
在次要服务器上,SQL Server使用msdb数据库的四个日志传送资料表。当SQL Server建立一个日志传送计划之后,它会新增一笔资料到log_shipping_plan资料表,用以纪录:主要与次要服务器的名称、档案位置、复制与回存工作ID(来自于次要服务器之sysjobs系统资料表)。在log_shipping_plan_databases资料表,SQL Server会连结维护计划以及来源/目的数据库名称,而且储存最后一次进行档案复制与加载动作的相关信息。log_shipping_plan_history资料表则是将每次日志传送的复制与回存事件纪录下来,连同该工作是否成功的信息。SQL Server也会新增一笔资料在log_shipping_monitor资料表,用以参照监控服务器。
如果您勾选了【Allow database to assume primary role】复选框,您将在次要服务器上看到一个重要的额外项目:另一个数据库维护计划(与您先前所建立的维护计划名称相同),但是并没有激活日志传送。您也会看到一个非作用中(disabled)的SQL Agent工作(备份该数据库的交易日志)。也许您会被这些项目所混淆。尽管它们的名字相同,但是此额外产生的维护计划却不同于当初所建立的那个。SQL Server保留第二个逆向维护计划是为了以后可能发生的主要/次要服务器角色对调动作所准备。
在监控服务器上检视日志传送动作当您正确设定日志传送之后,SQL Server 会激活监控服务器上Enterprise Manager 的日志传送监控工具程序。此外,SQL Server会建立两个SQL Agent 警示工作(alert job):一个用来执行工作,另一个处理out-of-sync情况。
使用监控工具程序的方式是,开启Enterprise Manager并连至监控服务器,展开【Management】节点,然后点选【记录传送监视器(Log Shipping Monitor)】。当您点选此工具程序时,其内会列出日志传送配对服务器的清单。您可在配对服务器上按下鼠标右键,检视其备份、复制与回存等工作的执行历史纪录。这些历史纪录十分有用,因为您从这里得到的错误讯息会比从次要服务器上(SQL Agent 复制与回存工作)得到的更为详尽。
如图所示:当您开启配对服务器之属性对话盒,并进入【Status】设定页时,您可检视此配对服务器执行备份与回存程序之状态。
其状态(Status)可以是Normal 或是Out-of-Sync。如果SQL Server Agent尚未复制或回存交易日志文件,对话盒内将会显示日志文件名为first_file_000000000000.trn。这并不是实际的文件名称,只不过是用来标示SQL Server Agent尚未处理任何档案而已。在【Status】设定页也会显示备份、复制以及加载(回存)等动作执行时所耗费的时间。此设定页之信息不会自动更新,所以您必须将此对话盒关闭后再开启,才能更新其资料。
SQL Server只使用msdb数据库内两个资料表来储存日志传送服务器之相关资料。SQL Server在这两个资料表中都给予一个ID做为连结,以及一个外来键(foreign key)。该外来键是设定在log_shipping_secondaries资料表上,并参照log_shipping_primaries资料表的primary_id字段(这两个是所有日志传送资料表中唯一具有外来键关系的资料表)。在log_shipping_primaries资料表内的每笔资料都包含日志传送的相关信息,例如:来源数据库名称、交易日志文件备份工作执行之状态,以及已规划的停摆信息(可避免不必要的警示讯息)。而log_shipping_secondaries 资料表之每笔资料关于目的数据库之信息;每个目的数据库附属于特定的日志传送来源数据库。这两个资料表互相连结的结果就是日志传送监控程序内所显示的配对服务器信息。
移除与重新组态日志传送功能
如果您想从数据库维护计划中移除日志传送功能,可参考下列方式:开启该计划的属性对话盒,选择【记录传送】设定页,然后点选【移出记录传送】。此动作将从次要服务器上移除SQL Server Agent的备份与回存工作,并清除日志传送资料表内的所有相关资料。此外,日志传送监控程序的相关信息也会一并被清除。然而此动作将会适当地保留主要服务器上SQL Server Agent的交易日志备份工作。只有在删除数据库维护计划时,该工作才会被移除。假如您想从监控服务器内移除掉日志传送监控程序,请用手动方式将log_shipping_primaries与log_shipping_secondaries这两个资料表(位于监控服务器的msdb数据库)的资料删除即可。
如果您在数据库维护计划内设定日志传送时,就已允许目的数据库可以做为新的日志传送来源数据库。当您删除主要服务器的维护计划时,次要服务器上仍然会保留其数据库维护计划,以及交易日志文件备份工作。删除这些项目的方式是将次要服务器上与日志传送相关的数据库维护计划直接删除。
篇2:如何修复SQLSERVER 数据库置疑之(二)数据库教程
server|sqlserver|数据|数据库|置疑
如果 SQL Server 因为磁盘可用空间不足,而不能完成数据库的恢复,那么 SQL Server 会返回错误 1105 并且将 sysdatabases 中的 status 列设为置疑,
你可以看到在SQLSERVER 的ERROR LOG 和OS的应用程序日志中应该有1105的错误信息:
SQL Server事务日志可能会被填满,这会阻止之后的数据库操作,包括UPDATE, DELETE, INSERT 和CHECKPOINT。
事务日志填满会导致1105错误:
Can't allocate space for object syslogs in database dbname because
the logsegment is full。 If you ran out of space in syslogs, dump
the transaction log。 Otherwise use ALTER DATABASE or
sp_extendsegment to increase the size of the segment。
这种现象可能出现于任何一个数据库中,包括Master和TempDB。一些难以预见的因素可能消耗日志空间。 例如:
一个大型事务, 尤其像批量数据更新、插入或删除。
一个未提交的事务。
检查点处理程序截除时所需的带宽过大。
截除时超过阈值
上述各种条件互相作用的结果。
用于发布的标记事务没有被日志读取程序读走
下面是修复的步骤和收缩日志的步骤:
1.在命令提示符下运行以下命令启动 SQL Server:
SQLSERVER -f -m
备注:-m 开关以单用户模式启动 SQL Server。在单用户模式下,只能成功建立一个连接。 请注意是否有任何其他客户机或服务可能会在您通过 SQL Server 查询分析器 建立连接前使用那个连接。
2. 重置置疑数据库的状态。
sp_resetstatus 'database_name'
下面是结果集:
Database'database_name'status reset!WARNING: You must reboot SQL Server prior to accessing this database!
3. 用 ALTER DATABASE 向数据库添加一个数据文件或日志文件:
USE masterGOCREATE DATABASE db_name ON( NAME = dbname_dat1, FILENAME = 'D:\MSSQL\Data\dbname_dat1.ndf', SIZE = 1000MB, FILEGROWTH = 50MB)GO
--更改该数据库以添加一个 2GB 大小的新数据文件ALTER DATABASE db_nameADD FILE ( NAME = dbname_dat2, FILENAME = 'F:\MSSQL\DATA\dbname_dat2.ndf', SIZE = 2000MB, FILEGROWTH = 50MB)GO--更改该数据库以添加一个1GB 大小的新日志文件ALTER DATABASE db_nameADD LOG FILE ( NAME = db_name_log2, FILENAME = 'F:\MSSQL\Data\db_name_log2.ldf', SIZE = 1000MB, FILEGROWTH = 20MB),GO
4. 停止并重新启动 SQL Server:
用新的数据文件或日志文件所提供的额外空间,SQL Server 应该能完成数据库的恢复。
5. 释放磁盘空间并且重新运行恢复操作,按照下面的步骤收缩日志。
sp_resetstatus 关闭数据库的置疑标志,但是原封不动地保持数据库的其它选项。
为从根本上解决这样的问题,你可以按下面的操作配置SQLSERVER 2000:
a.如果不需要恢复到指定的时间点,你可以将数据库的恢复模式配置为简单,这样
UPDATE,DELETE,SELECT就不会记录日志,日志就不会增加的很大:
USE MASTER
GO
ALTER DATABASE DB_NAME SET RECOVERY SIMPLE
b.如果你的恢复模式是全部,你一定要配置日志字段收缩:
USE MASTER
GO
sp_dboption 'databasename','trunc. log on chkpt.',true
sp_dboption 'databasename','autoshrink',true
c.通过每日备份将日志收缩:
BACKUP DATABASE DATABASE_NAME TO BACKUP_DEVICES
BACKUP LOG DATABASE_NAME TO LOG_DEVICES
OR
BACKUP LOG DATABASE_NAME with truncate_only
**检查日志的容量:DBCC SQLPERF (LOGSPACE) 这时日志并没有收缩!
d.每天在备份数据库完成之后,重新启动MS SQLSERVER SERVICE.
USE DATABASE_NAME
go
DBCC SHRINKFILE(2,truncateonly)
**检查日志的容量:DBCC SQLPERF (LOGSPACE) 这时日志已经收缩!
e.手动快速收缩日志:
/ *run below script,you will shrink you database log files
immediately, in my experience,you need to run the script for 3 or
4 minutes before stopping it manually */
use databasename
dbcc shrinkfile(2,notruncate)
dbcc shrinkfile(2,truncateonly)
create table t1(char1 char(4000))
go
declare @i int
select @i=0
while(1=1)
begin
while(@i<100)
begin
INSERT INTO T1 VALUES ('A')
SELECT @I=@I+1
END
TRUNCATE table T1
BACKUP LOG youdatabasename with truncate_only
end
GO
注意 只有在您的主要支持提供者指导下或有疑难解答建议的做法时,才可以使用
sp_resetstatus,
否则,可能会损坏数据库。
由于该过程修改了系统表,系统管理员必须在运行 sp_resetstatus这个过程前,启用系统表更新。要
启 用更新,使用下面的过程:
USE master
GO
sp_configure 'allow updates', 1
GO
RECONFIGURE WITH OVERRIDE
GO
过程创建后,立即禁用系统表更新:
sp_configure 'allow updates', 0
GO
RECONFIGURE WITH OVERRIDE
GO
只有系统管理员才能执行 sp_resetstatus。执行该过程后,立即关闭 SQL Server。
请参考:
support.microsoft.com/default.aspx?scid=kb;zh-cn;317375
support.microsoft.com/default.aspx?scid=kb;zh-cn;307775
篇3:sqlserver 如何创建分区表数据库教程
server|sqlserver|创建
该文详细介绍实现分区表的过程以及有助于完成此过程的功能,sqlserver 2005 如何创建分区表数据库教程
。逻辑流程如下:图:创建分区表或索引的步骤
确定是否应为对象分区
虽然分区可以带来众多的好处,但也增加了实现对象的管理费用和复杂性,这可能是得不偿失的。尤其是,您可能不需要为较小的表或目前满足性能和维护要求的表分区。前面提到的销售方案使用分区减轻了移动行和数据的负担,但在决定是否实现分区时,您应考虑您的方案是否存在这种负担。
确定分区键和分区数
如果您正在尝试改善大型数据子集的性能和可管理性,并且已经定义了访问模式,则可以使用范围分区减少数据争用的情况,同时减少只读数据不需要分区时的维护工作。要确定分区数,应先评估您的数据中是否存在逻辑分组和模式。如果您通常一次只处理这些已定义子集中的少数几个,则应定义范围以隔离查询,使其只处理相应的数据(即,只处理特定的分区)。
确定是否应使用多个文件组
为了有助于优化性能和维护,应使用文件组分离数据。文件组的数目一定程度上由硬件资源决定:一般情况下,文件组数最好与分区数相同,并且这些文件组通常位于不同的磁盘上。但是,这主要适用于打算对整个数据集进行分析的系统。如果您有多个 CPU,SQL Server 则可以并行处理多个分区,从而大大缩短处理大量复杂报表和分析的总体时间。这种情况下,可以获得并行处理以及在分区表中移入和移出分区的好处。
创建文件组
如果需要为多个文件放置一个分区表以获得更好的 I/O平衡,则至少需要创建一个文件组。文件组可以由一个或多个文件构成,而每个分区必须映射到一个文件组。一个文件组可以由多个分区使用,但是为了更好地管理数据(例如,为了获得更精确的备份控制),应该对分区表进行设计,以便只有相关数据或逻辑分组的数据位于同一个文件组中。使用 ALTER DATABASE,可以添加逻辑文件组名,然后添加文件。要为 AdventureWorks 数据库创建名为 Q3 的文件组,请按以下方式使用 ALTER DATABASE:
ALTER DATABASE AdventureWorks ADD FILEGROUP [2003Q3]
创建文件组后,使用 ALTER DATABASE 将文件添加到该文件组中。
ALTER DATABASE AdventureWorks
ADD FILE
(NAME = N'2003Q3',
FILENAME = N'C:\AdventureWorks\2003Q3.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB)
TO FILEGROUP [2003Q3]
通过在 CREATE TABLE 的 ON 子句中指定一个文件组,可以为文件创建一个表。但是,如果表未分区,则不能为多个文件组创建一个表。要为一个文件组创建表,请使用 CREATE TABLE 的 ON 子句。要创建分区表,必须先确定分区的功能机制。进行分区的标准以分区函数的形式从逻辑上与表相分离。此分区函数作为独立于表的定义存在,而这种物理分离将起到帮助作用,因为多个对象都可以使用该分区函数。因此,为表分区的第一步是创建分区函数。
为范围分区创建分区函数
范围分区必须使用边界条件进行定义。而且,即使通过 CHECK 约束对表进行了限制,也不能消除该范围任一边界的值。为了允许定期将数据移入该表,需要创建最后一个空分区。
在范围分区中,首先定义边界点:如果存在五个分区,则定义四个边界点值,并指定每个值是第一个分区的上边界 (LEFT) 还是第二个分区的下边界 (RIGHT)。根据 LEFT 或 RIGHT 指定,始终有一个空分区,因为该分区没有明确定义的边界点。
具体来讲,如果分区函数的第一个值(或边界条件)是 '20001001',则边界分区中的值将是:
对于 LEFT
第一个分区是所有小于或等于 '20001001' 的数据
第二个分区是所有大于 '20001001' 的数据
对于 RIGHT
第一个分区是所有小于 '20001001' 的数据
第二个分区是所有大于或等于 '20001001' 数据
由于范围分区可能在 datetime 数据中进行定义,因此必须了解其含义。使用datetime具有某种含义:即总是同时指定日期和时间。未定义时间值的日期表示时间部分为“0”的 12:00 A.M。如果将 LEFT 与此类数据结合使用,则日期为 10 月 1 日 12:00 A.M. 的数据将位于第一个分区,而 10 月份的其他数据将位于第二个分区。从逻辑上讲,最好将开始值与 RIGHT 结合使用,而将结束值与 LEFT 结合使用。下面的三个子句将创建逻辑上相同的分区结构:
RANGE LEFT FOR VALUES ('20000930 23:59:59.997',
'20001231 23:59:59.997',
'0331 23:59:59.997',
'20010630 23:59:59.997')
或
RANGE RIGHT FOR VALUES ('20001001 00:00:00.000', '20010101 00:00:00.000', '20010401 00:00:00.000', '20010701 00:00:00.000')
或
RANGE RIGHT FOR VALUES ('20001001', '20010101', '20010401', '20010701')
注意:此处使用 datetime 数据类型确实增加了一定的复杂性,但您需要确保设置正确的边界情况。请注意使用 RIGHT 的简单性,因为默认时间为 12:00:00.000 A.M。对于 LEFT,复杂性增加是因为 datetime 数据类型具有精度。必须选择 23:59:59.997 的原因在于,datetime 数据无法保证毫秒级别的精度。相反,datetime 数据的精度在 3.33 毫秒内。使用 23:59:59.999 这个确切的时间值是不行的,因为该值将被舍入到最接近的时间值,即第二天的 12:00:00.000 A.M。由于进行了这种舍入,将无法正确定义边界,
对于 datetime 数据,必须对明确提供的毫秒值加倍小心。
注意:分区函数还允许将函数作为分区函数定义的一部分。您可以使用 DATEADD(ms,-3,'20010101'),而不是使用 '20001231 23:59:59.997' 明确定义时间。
要在四个活动分区(每个分区代表一个日历季度)中存储四分之一的 Orders 数据,并创建第五个分区以备将来使用(还是作为占位符,用于在分区表中移入和移出数据),请将 LEFT 分区函数与以下四个边界条件结合使用:
CREATE PARTITION FUNCTION OrderDateRangePFN(datetime)
AS
RANGE LEFT FOR VALUES ('20000930 23:59:59.997',
'20001231 23:59:59.997',
'20010331 23:59:59.997',
'20010630 23:59:59.997')
记住,定义四个边界点将创建五个分区。通过查看以下数据集检查此分区创建的数据集:
边界点 '20000930 23:59:59.997' 作为 LEFT(设置模式):
最左侧的分区将包含所有小于或等于 '20000930 23:59:59.997' 的值
边界点 '20001231 23:59:59.997':
第二个分区将包含所有大于 '20000930 23:59:59.997' 但小于或等于 '20001231 23:59:59.997' 的值
边界点 '20010331 23:59:59.997':
第三个分区将包含所有大于 '20001231 23:59:59.997' 但小于或等于 '20010331 23:59:59.997' 的值
边界点 '20010630 23:59:59.997':
第四个分区将包含所有大于 '20010331 23:59:59.997' 但小于或等于 '20010630 23:59:59.997' 的值
最后,第五个分区将包含所有大于 '20010630 23:59:59.997' 的值。
创建分区架构
创建分区函数后,必须将其与分区架构相关联,以便将分区定向至特定的文件组。定义分区架构时,即使多个分区位于同一个文件组中,也必须为每个分区指定一个文件组。对于前面创建的范围分区 (OrderDateRangePFN),存在五个分区;最后一个空分区将在 PRIMARY 文件组中创建。因为此分区永远不包含数据,所以不需要指定特殊的位置。
CREATE PARTITION SCHEME OrderDatePScheme
AS
PARTITION OrderDateRangePFN
TO ([2000Q3], [2000Q4], [2001Q1], [2001Q2], [PRIMARY])
注意:如果所有分区都位于同一个文件组中,则可以使用以下更简单的语法:
CREATE PARTITION SCHEME OrderDatePScheme
AS
PARTITION OrderDateRangePFN
ALL TO ([PRIMARY])
创建分区表
定义分区函数(逻辑结构)和分区架构(物理结构)后,即可创建表来利用它们。表定义应使用的架构,而架构又定义函数。要将这三者结合起来,必须指定应该应用分区函数的列。范围分区始终只映射到表中的一列,此列应与分区函数中定义的边界条件的数据类型相匹配。另外,如果表应明确限制数据集(而不是从负无穷大到正无穷大),则还应添加 CHECK 约束。
CREATE TABLE [dbo].[OrdersRange]
(
[PurchaseOrderID] [int] NOT NULL,
[EmployeeID] [int] NULL,
[VendorID] [int] NULL,
[TaxAmt] [money] NULL,
[Freight] [money] NULL,
[SubTotal] [money] NULL,
[Status] [tinyint] NOT NULL ,
[RevisionNumber] [tinyint] NULL ,
[ModifiedDate] [datetime] NULL ,
[ShipMethodID] [tinyint] NULL,
[ShipDate] [datetime] NOT NULL,
[OrderDate] [datetime] NOT NULL
CONSTRAINT OrdersRangeYear
CHECK ([OrderDate] >= '20030701'
AND [OrderDate] <= '0630 11:59:59.997'),
[TotalDue] [money] NULL
)
ON OrderDatePScheme (OrderDate)
GO
建立索引:是否分区?
默认情况下,分区表中创建的索引也使用相同的分区架构和分区列。如果属于这种情况,索引将与表对齐。尽管未作要求,但将表与其索引对齐可以使管理工作更容易进行,对于滑动窗口方案尤其如此。
例如,要创建唯一的索引,分区列必须是一个关键列;这将确保对相应的分区进行验证,以保证索引的唯一性。因此,如果需要在一列上对表进行分区,而必须在另一个列上创建唯一的索引,这些表和索引将无法对齐。在这种情况下,可以在唯一的列(如果是多列的唯一键,则可以是任一关键列)中对索引进行分区,或者根本就不进行分区。请注意,在分区表中移入和移出数据时,必须删除和创建此索引。
注意:如果您打算使用现有数据加载表并立即在其中添加索引,则通常可以通过以下方式获得更好的性能:先加载到未分区、未建立索引的表中,然后在加载数据后创建分区索引。通过为分区架构定义群集索引,可以在加载数据后更有效地为表分区。这也是为现有表分区的不错方法。要创建与未分区表相同的表并创建与已分区群集索引相同的群集索引,请用一个文件组目标位置替换创建表中的 ON 子句。然后,在加载数据之后为分区架构创建群集索引。
篇4:有关日志压缩数据库教程
压缩
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO
CREATE PROCEDURE strink_logspace
AS
SET NOCOUNT ON
DECLARE @LogicalFileName sysname,
@MaxMinutes INT,
@NewSize INT
SELECT @LogicalFileName = rtrim(name),
@MaxMinutes = 10, -- 最大执行时间
@NewSize = 10 -- 最小空间
from sysfiles where status & 0x40 = 0x40
-- Setup / initialize
DECLARE @OriginalSize int
SELECT @OriginalSize = size -- in 8K pages
FROM sysfiles
WHERE name = @LogicalFileName
SELECT db_name +'日志原始大小' +
CONVERT(VARCHAR(30),@OriginalSize) + ' pages/ 8K 或 ' +
CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
FROM sysfiles
WHERE name = @LogicalFileName
CREATE TABLE DummyTrans
(DummyColumn char (8000) not null)
-- Wrap log and truncate it.
DECLARE @Counter INT,
@StartTime DATETIME,
@TruncLog VARCHAR(255)
SELECT @StartTime = GETDATE(),
@TruncLog = 'BACKUP LOG ['+ db_name() + '] WITH TRUNCATE_ONLY'
-- Try an initial shrink.
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
EXEC (@TruncLog)
-- Wrap the log if necessary.
WHILE @MaxMinutes >DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName) -- the log has not shrunk
AND (@OriginalSize * 8 /1024) >@NewSize -- The value passed in for new size is smaller than the current size.
BEGIN -- Outer loop.
SELECT @Counter = 0
WHILE ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
BEGIN -- update
INSERT DummyTrans VALUES ('Fill Log') -- Because it is a char field it inserts 8000 bytes.
DELETE DummyTrans
SELECT @Counter = @Counter + 1
END -- update
EXEC (@TruncLog) -- See if a trunc of the log shrinks it.
END -- outer loop
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
SELECT db_name() +'日志最后大小' +
CONVERT(VARCHAR(30),size) + ' pages/ 8K 或 ' +
CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
FROM sysfiles
WHERE name = @LogicalFileName
DROP TABLE DummyTrans
PRINT '*** 数据库日志压缩成功 ***'
SET NOCOUNT OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
--used
exec strink_logspace
篇5:远程管理sqlserver的注册方法数据库教程
server|sqlserver
如果是在同一个局域网内的数据库可以直接操作第二个步骤它会自动搜索到局域网内的所以sqlserver数据库
但是如果是在不同局域网内的数据库就需要通过ip来访问步骤如下:
1、点击开始 -- 程序 -- Microsoft SQL Server -- 客户端网络实用工具 -- 另名 -- 点击添加 --- 网络库选取TCP/IP;服务器别名:数据库服务器的IP;服务器名称:数据库服务器的IP;端口默认1433(查清远程的端口是什么!) -- 确定
2、点击开始 -- 程序 -- Microsoft SQL Server -- 企业管理器 -- Mouse点 Microsoft SQL Servers -- mouse右键点 Sql Server 组;点新的sql server 注册.... -- 下一步 -- 增加主机IP,下一步---选“系统管理员给我分配的SQL Server登录信息....”. ,
远程管理sqlserver的注册方法数据库教程
,
。。。。。
篇6:win 安装 sqlserver 的方法数据库教程
复制代码代码如下:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion]
“ProductId”=“69713-640-9722366-45198”
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion]
“CurrentBuild”=“1.511.1 (Obsolete data - do not use)”
“InstallDate”=dword:3f6c976d
“ProductName”=“Microsoft Windows Server 2003”
“RegDone”=“”
“SoftwareType”=“SYSTEM”
“CurrentVersion”=“5.2”
“CurrentBuildNumber”=“3790”
“BuildLab”=“3790.srv03_rtm.030324-2048”
“CurrentType”=“Uniprocessor Free”
“ProductId”=“69713-640-9722366-45198”
“DigitalProductId”=hex:a4,00,00,00,03,00,00,00,36,39,37,31,33,2d,36,34,30,2d,\
39,37,32,32,33,36,36,2d,34,35,31,39,38,00,5a,00,00,00,41,32,32,2d,30,30,30,\
30,31,00,00,00,00,00,00,00,00,e5,3f,e9,6a,2c,ed,25,35,12,ec,11,c9,8d,01,00,\
00,00,00,00,37,03,6d,3f,44,22,06,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,31,32,32,32,30,00,00,00,00,00,00,00,dc,0f,\
00,00,bf,4a,94,6c,80,00,00,00,15,18,00,00,00,00,00,00,00,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,34,79,ca,d7
“LicenseInfo”=hex:71,84,c7,56,a0,d6,10,6e,70,b4,9f,e9,10,1a,1e,7a,01,a4,41,09,\
25,20,0e,80,83,80,1f,31,27,86,64,1f,31,dc,22,af,f7,7d,aa,e4,2a,b9,e5,e3,6c,\
e2,01,69,85,70,91,be,a7,9f,95,e5
篇7:关于在SQLSERVER里调用COM组件数据库教程
server
Sql-server里可以调用基于IDispatch的COM组件
有兴趣的可以自己去查SQL帮助里的sp_OACreate、sp_OAMethod、sp_OADestroy等存储过程的用法,
下面是我在一个短信报警的小项目里的一些sql代码,报警信息通过各类软件插入到sql-server里,然后通过触发器调用组件,并发送短信到指定手机上去,实现自动报警功能。
//测试数据库的触发器
ALTER TRIGGER message_Trigger1
ON dbo.message
FOR INSERT /*, UPDATE, DELETE */
AS
/* IF UPDATE (column_name) ...*/
begin
declare @PhoneNum nvarchar(50)
declare @Content nvarchar(140)
declare @MessageId nvarchar(70)
declare @index int
declare @hr int
declare @object int
select @PhoneNum = phone_num, @Content = Content, @MessageId = message_id from inserted
select @index = 1
/*调用COM发送短信*/
begin
EXEC @hr = sp_OACreate '{26850DDA-862C-44FF-9232-282937F2CA4B}',@object OUT
if @hr = 0
begin
exec @hr=sp_OAMethod @object,'SendMsg',NULL,@Content,@PhoneNum,@index,@MessageId
exec sp_OADestroy @object
end
end
end
这里的代码可以说是没有问题,但是也可以说是有很大的问题,
关键就在于组件的SendMsg方法,为什么呢?我可以举出几个我实际碰到的问题来做具体说明。
最主要有2点
第1:此COM组件是否为进程内组件,组件内部代码是否足够强壮
第2:创建组件和销毁组件及组件方法要尽最大可能的快速
我对上述两点做一个说明
如果COM组件为进程内组件的话,意味着此组件被sql-server加载,如果此代码不够健壮,那么,由于组件本身导致的挂起,崩溃,会直接影响到整个sql-server,那么情况是非常严重的,这种错误,发生一次就足以要了你的小命,如果恰好在客户的脸上爆炸的话……
解决的方法只有这样:首先保证你的组件代码足够强壮,强壮到不能再强壮为止。还有就是尽量让组件不要是进程内的,如果已经是DLL了,那么就交给COM+ Catalog来管理。这样就解决了因为组件崩溃挂起导致sql-server产生问题。
其次,要让你的组件的创建、方法调用、销毁都快到不能再快,要快到几乎瞬间就完成。否则如果突然有海量数据进来,你的触发器来不及反映,那你的数据就可能被回滚掉,而且这些数据很重要,那你就等着被Fire吧 L 5555~~~~~
如果非要用这种方法的话,那么就要完成我上面提到的2点,并且最好启用COM+对象池。如果方法需要很长时间才能返回,并且无法优化了,那么就把这些方法移出去,把这些动作在另外的程序里做,让COM方法立刻返回。
总而言之,言而总之,在系统集成的时候如果几个开发厂商没有商量好接口,并且都采用SQL-SERVER数据库,那么关于此类数据的操作,似乎用这样的方法就是最好的补救。
个人觉得有点剑走偏锋的感觉,虽然很锋利,但是难免伤到自己
篇8:[引]SQLServer和Access、Excel数据传输简单总结数据库教程
access|excel|server|sqlserver|数据
www.tongyi.net/article/1101/200311013786.shtml
所谓的数据传输,其实是指SQLServer访问Access、Excel间的数据,
为什么要考虑到这个问题呢?
由于历史的原因,客户以前的数据很多都是在存入在文本数据库中,如Acess、Excel、Foxpro。现在系统升级及数据库服务器如SQLServer、ORACLE后,经常需要访问文本数据库中的数据,所以就会产生这样的需求。前段时间出差的项目,就是面临这样的一个问题:SQLServer和VFP之间的数据交换。
要完成标题的需要,在SQLServer中是一件非常简单的事情。
通常的可以有3种方式:1、DTS工具 2、BCP 3、分布式查询
DTS就不需要说了,因为那是图形化操作界面,很容易上手。
这里主要讲下后面两们,分别以查、增、删、改作为简单的例子:
下面废话就不说了,直接以T-SQL的形式表现出来。
一、SQLServer和Access
1、查询Access中数据的方法:
select * from OpenRowSet('microsoft.jet.oledb.4.0',';database=c:\db2.mdb','select * from serv_user')
或
select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0','Data Source=“c:\DB2.mdb”;User ID=Admin;Password=')...serv_user
2、从SQLServer向Access写数据:
insert into OpenRowSet('microsoft.jet.oledb.4.0',';database=c:\db2.mdb','select * from Accee表')
select * from SQLServer表
或用BCP
master..xp_cmdshell'bcp “serv-htjs.dbo.serv_user” out “c:\db3.mdb” -c -q -S“.” -U“sa” -P“sa”'
上面的区别主要是:OpenRowSet需要mdb和表存在,BCP会在不存在的时候生成该mdb
3、从Access向SQLServer写数据:有了上面的基础,这个就很简单了
insert into SQLServer表 select * from
OpenRowSet('microsoft.jet.oledb.4.0',';database=c:\db2.mdb','select * from Accee表')
或用BCP
master..xp_cmdshell'bcp “serv-htjs.dbo.serv_user” in “c:\db3.mdb” -c -q -S“.” -U“sa” -P“sa”'
4、删除Access数据:
delete from OpenRowSet('microsoft.jet.oledb.4.0',';database=c:\db2.mdb','select * from serv_user')
where lock=0
5、修改Access数据:
update OpenRowSet('microsoft.jet.oledb.4.0',';database=c:\db2.mdb','select * from serv_user')
set lock=1
SQLServer和Access大致就这么多,
二、SQLServer和Excel
1、向Excel查询
select * from OpenRowSet('microsoft.jet.oledb.4.0','Excel 8.0;HDR=yes;database=c:\book1.xls;','select * from [Sheet1$]') where c like '%f%'
select * from
OPENROWSET('MICROSOFT.JET.OLEDB.4.0'
,'Excel 5.0;HDR=YES;IMEX=2;DATABASE=c:\book1.xls',[sheet1$])
1)hdr=yes时可以把xls的第1行作为字段看待,如第1个中hdr=no的话,where时就会报错
2)[]和美圆$必须要,否则M$可不认这个账
2、修改Execl
update OpenRowSet('microsoft.jet.oledb.4.0','Excel 8.0;hdr=yes;database=c:\book1.xls;','select * from [Sheet1$]')
set a='erquan' where c like '%f%'
3、导入导出
insert into OpenRowSet('microsoft.jet.oledb.4.0','Excel 8.0;hdr=yes;database=c:\book1.xls;','select * from [Sheet2$]')(id,name)
select id,name from serv_user
或BCP
master..xp_cmdshell'bcp “serv-htjs.dbo.serv_user” out “c:\book2.xls” -c -q -S“.” -U“sa” -P“sa”'
从Excel向SQLServer导入:
select * into serv_user_bak
from OpenRowSet('microsoft.jet.oledb.4.0','Excel 8.0;HDR=yes;database=c:\book1.xls;','select * from [Sheet1$]')
如果表serv_user_bak不存在,则创建
有关BCP和分布式查询的详细解答,就查SQLServer自带的帮助吧。
SQLServer和txt文件、HTML文件、VFP文件的数据交换都显得非常容易了。。。。
其实这些内容在帮助里都有,偶只不过是总结了一下,方便大家参考,呵呵~~
以上内容都经过测试~~
篇9:用脚本缩小数据库日志数据库教程
脚本|数据|数据库
因为客户使用的数据库时常因为日志过大而导致硬盘空间不够,或者备份出来的文件太大无法通过邮件传送,
闲下有余,参考SQLSERVER的帮助文件,写了如下脚本,可以截断日志,以达到缩小文件的目的。有空大家可以在自己的SQLSERVER上测试下效果哦。。。:)也许对有些情况导致的日志过大没有作用,这点可以同各位同仁互相交流下。
--在MASTER数据库中执行以下脚本(使用查询分析器)
declare @dbname varchar(50)
declare temp_cur cursor scroll for select name from sysdatabases
open temp_cur
fetch first from temp_cur into @dbname
while @@fetch_status =0
begin
exec ('backup log '+@dbname+' with no_log')
exec ('dbcc shrinkdatabase('+@dbname+')')
exec ('dbcc checkcatalog ('+@dbname+')')
exec ('dump transaction '+@dbname+' with no_log')
fetch next from temp_cur into @dbname
end
close temp_cur
deallocate temp_cur












