网站运维、系统运维管理研究

如何监测你的SQL SERVER

当您怀疑计算机硬件是影响SQL Server运行性能的主要原因时,可以通过SQL Server Performance Monitor监视相应硬件的负载,以证实您的猜测并找出系统瓶颈。下文将介绍一些常用的分析对象及其参数。

  Memory: Page Faults / sec

  如果该值偶尔走高,表明当时有线程竞争内存。如果持续很高,则内存可能是瓶颈。

  Process: Working Set

  SQL Server的该参数应该非常接近分配给SQL Server的内存值。在SQL Server设定中,如果将"set working set size"置为0, 则Windows NT会决定SQL Server的工作集的大小。如果将"set working set size"置为1,则强制工作集大小为SQLServer的分配内存大小。一般情况下,最好不要改变"set working set size"的缺省值。

  Process:%Processor Time

  如果该参数值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。

  Processor:%Privileged Time

  如果该参数值和"Physical Disk"参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。另外设置Tempdb in RAM,减低"max async IO","max lazy writer IO"等措施都会降低该值。

  Processor:%User Time

  表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。

  Physical Disk:Avg.Disk Queue Length

  该值应不超过磁盘数的1.5~2倍。要提高性能,可增加磁盘。

  注意:一个Raid Disk实际有多个磁盘。

  SQLServer:Cache Hit Ratio

  该值越高越好。如果持续低于80%,应考虑增加内存。 注意该参数值是从SQL Server启动后,就一直累加记数,所以运行经过一段时间后,该值将不能反映系统当前值。

SQL Server的用户及权限

Sybase中的用户分为两种:SQL服务器用户(登录帐号)和数据库用户。 安装完SQL服务器后,系统自动建立一个SQL服务器用户sa,口令为空,即系统管理员,他对整个系统有操作权,其他用户均由系统管理员建立。

在SQL Server中有三种特殊的用户:系统管理员、用户数据库所有者(建立相应数据库的数据库用户)DBO、一般用户。系统管理员对整个系统有操作权;用户数据库所有者对他所建立的数据库具有全部操作权利;一般用户对给定的数据库只有被授权的操作权限。

数据库用户一般可分为用户组,任一数据库在建立后即被赋予一个用户组public。

1、建立SQL服务器用户名(登录帐号)

作为一个用户,为了使用SQL Server,他必须在SQL Server上有一个SQL服务器用户名(登录帐号)。这个帐号是系统管理员通过sp_addlogin来增加的。

sp_addlogin 登录名,口令,库名,语言,全名

例:建立用户zhang, 口令为zhangling(最低六位),全名为Zhang ling

1> sp_addlogin zhang,zhangling,null,null,Zhang ling

2> go

3> select * from syslogins

4> go

2、增加数据库用户名

同样,为了使用SQL Server上的数据库,他必须在数据库中有一个用户名,这个用户名是数据库所有者通过sp_adduser来增加的。数据库用户名不必和用户帐户一样,而且在不同的数据库中用户名可以不同。多个用户可以有相同的SQL Server帐户。同样,多个SQL Server帐户可以有相同的数据库名。

sp_adduser 登录名,别名,组名

登录名为用户的SQL服务器登录名;别名为用户在数据库中的用户名;组名为用户所属的数据库用户组。

例:用户zhang增加为tele114的用户,别名为zhang1,属于用户组china

1>sp_addgroup china

2>go

1>sp_adduser zhang,zhang1,china

2>go

1> sp_helpuser

2> go

*例:删除别名zhang1,用户组china,登录名zhang

1> use tele114

2> go

3> sp_dropuser zhang1

4> go

5> sp_helpuser

6> go

1>sp_dropgroup china

2>go

1> sp_helpgroup

2> go

3> use master

4> go

5> sp_droplogin zhang

6> go

7> select * from syslogins

8> go

3、数据库操作授权

grant 命令序列 to 用户名

A. 系统管理员可以授予其他用户Create DATABASE的权限,使其他用户可以成为数据库所有者。

B. 数据库所有者在他所拥有的数据库中,可以授予其他用户的权限有:

l Create TABLE ——————- 建表

lCreate DEFAULT —————— 建缺省

lCreate RULE ——————- 建规则

lCreate PROCedure —————— 建存储过程

lCreate VIEW ——————- 建视图

lDUMP DATABASE ——————- 备份数据库

lDUMP TRANsaction —————— 备份日志

C. 数据库对象所有者可以授予其他用户的操作权限有:

l Select

l Update

l Insert

l EXECute

l Delete

l REFERENCE

例:授予zhang1在数据库tele114上建表,建视图,建存储过程;对表students有select,reference权;对name,native字段有update权。

1> use tele114

2> go

3> grant creat table,create procedure ,create view to zhang1

4> go

5> grant select,reference on students to zhang1 with grant option 6> go

7> grant update on students(name,native) to zhang1

8> go

9> sp_helprotect

10> go

将表数据生成SQL脚本的存储过程

Cr&#101;ate&amp;nbsp;PROCEDURE&amp;nbsp;dbo.UspOutputData&amp;nbsp;<br />@tablename&amp;nbsp;sysname&amp;nbsp;<br />AS&amp;nbsp;<br />declare&amp;nbsp;@column&amp;nbsp;varchar(1000)&amp;nbsp;<br />declare&amp;nbsp;@columndata&amp;nbsp;varchar(1000)&amp;nbsp;<br />declare&amp;nbsp;@sql&amp;nbsp;varchar(4000)&amp;nbsp;<br />declare&amp;nbsp;@xtype&amp;nbsp;tinyint&amp;nbsp;<br />declare&amp;nbsp;@name&amp;nbsp;sysname&amp;nbsp;<br />declare&amp;nbsp;@objectId&amp;nbsp;int&amp;nbsp;<br />declare&amp;nbsp;@objectname&amp;nbsp;sysname&amp;nbsp;<br />declare&amp;nbsp;@ident&amp;nbsp;int&amp;nbsp;<br /><br />set&amp;nbsp;nocount&amp;nbsp;on&amp;nbsp;<br />set&amp;nbsp;@objectId=object_id(@tablename)&amp;nbsp;<br /><br />if&amp;nbsp;@objectId&amp;nbsp;is&amp;nbsp;null&amp;nbsp;–&amp;nbsp;判斷對象是否存在&amp;nbsp;<br />begin&amp;nbsp;<br />print&amp;nbsp;&#39;The&amp;nbsp;object&amp;nbsp;not&amp;nbsp;exists&#39;&amp;nbsp;<br />return&amp;nbsp;<br />end&amp;nbsp;<br />set&amp;nbsp;@objectname=rtrim(object_name(@objectId))&amp;nbsp;<br /><br />if&amp;nbsp;@objectname&amp;nbsp;is&amp;nbsp;null&amp;nbsp;or&amp;nbsp;charindex(@objectname,@tablename)=0&amp;nbsp;–此判断不严密&amp;nbsp;<br />begin&amp;nbsp;<br />print&amp;nbsp;&#39;object&amp;nbsp;not&amp;nbsp;in&amp;nbsp;current&amp;nbsp;database&#39;&amp;nbsp;<br />return&amp;nbsp;<br />end&amp;nbsp;<br /><br />if&amp;nbsp;OBJECTPROPERTY(@objectId,&#39;IsTable&#39;)&amp;nbsp;&amp;lt;&amp;nbsp;&amp;gt;&amp;nbsp;1&amp;nbsp;–&amp;nbsp;判斷對象是否是table&amp;nbsp;<br />begin&amp;nbsp;<br />print&amp;nbsp;&#39;The&amp;nbsp;object&amp;nbsp;is&amp;nbsp;not&amp;nbsp;table&#39;&amp;nbsp;<br />return&amp;nbsp;<br />end&amp;nbsp;<br /><br />sel&#101;ct&amp;nbsp;@ident=status&amp;amp;0×80&amp;nbsp;from&amp;nbsp;syscolumns&amp;nbsp;wh&#101;re&amp;nbsp;id=@objectid&amp;nbsp;and&amp;nbsp;status&amp;amp;0×80=0×80&amp;nbsp;<br /><br />if&amp;nbsp;@ident&amp;nbsp;is&amp;nbsp;not&amp;nbsp;null&amp;nbsp;<br />print&amp;nbsp;&#39;SET&amp;nbsp;IDENTITY_Ins&#101;rt&amp;nbsp;&#39;+@TableName+&#39;&amp;nbsp;ON&#39;&amp;nbsp;<br /><br />declare&amp;nbsp;syscolumns_cursor&amp;nbsp;cursor<br /><br />for&amp;nbsp;sel&#101;ct&amp;nbsp;c.name,c.xtype&amp;nbsp;from&amp;nbsp;syscolumns&amp;nbsp;c&amp;nbsp;wh&#101;re&amp;nbsp;c.id=@objectid&amp;nbsp;order&amp;nbsp;by&amp;nbsp;c.colid&amp;nbsp;<br /><br />open&amp;nbsp;syscolumns_cursor&amp;nbsp;<br />set&amp;nbsp;@column=&#39;&#39;&amp;nbsp;<br />set&amp;nbsp;@columndata=&#39;&#39;&amp;nbsp;<br />fetch&amp;nbsp;next&amp;nbsp;from&amp;nbsp;syscolumns_cursor&amp;nbsp;into&amp;nbsp;@name,@xtype&amp;nbsp;<br /><br />while&amp;nbsp;@@fetch_status&amp;nbsp;&amp;lt;&amp;nbsp;&amp;gt;-1&amp;nbsp;<br />begin&amp;nbsp;<br />if&amp;nbsp;@@fetch_status&amp;nbsp;&amp;lt;&amp;nbsp;&amp;gt;-2&amp;nbsp;<br />begin&amp;nbsp;<br />if&amp;nbsp;@xtype&amp;nbsp;not&amp;nbsp;in(189,34,35,99,98)&amp;nbsp;–timestamp不需处理,image,text,ntext,sql_variant&amp;nbsp;暂时不处理&amp;nbsp;<br /><br />begin&amp;nbsp;<br />set&amp;nbsp;@column=@column+case&amp;nbsp;when&amp;nbsp;len(@column)=0&amp;nbsp;then&#39;&#39;&amp;nbsp;else&amp;nbsp;&#39;,&#39;end+@name&amp;nbsp;<br /><br />set&amp;nbsp;@columndata=@columndata+case&amp;nbsp;when&amp;nbsp;len(@columndata)=0&amp;nbsp;then&amp;nbsp;&#39;&#39;&amp;nbsp;else&amp;nbsp;&#39;,&#39;&#39;,&#39;&#39;,&#39;<br />end&amp;nbsp;<br /><br />+case&amp;nbsp;when&amp;nbsp;@xtype&amp;nbsp;in(167,175)&amp;nbsp;then&amp;nbsp;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;+&#39;+@name+&#39;+&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&amp;nbsp;–varchar,char&amp;nbsp;<br />when&amp;nbsp;@xtype&amp;nbsp;in(231,239)&amp;nbsp;then&amp;nbsp;&#39;&#39;&#39;N&#39;&#39;&#39;&#39;&#39;&#39;+&#39;+@name+&#39;+&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&amp;nbsp;–nvarchar,nchar&amp;nbsp;<br />when&amp;nbsp;@xtype=61&amp;nbsp;then&amp;nbsp;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;+convert(char(23),&#39;+@name+&#39;,121)+&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&amp;nbsp;–datetime&amp;nbsp;<br />when&amp;nbsp;@xtype=58&amp;nbsp;then&amp;nbsp;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;+convert(char(16),&#39;+@name+&#39;,120)+&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&amp;nbsp;–smalldatetime&amp;nbsp;<br />when&amp;nbsp;@xtype=36&amp;nbsp;then&amp;nbsp;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;+convert(char(36),&#39;+@name+&#39;)+&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&amp;nbsp;–uniqueidentifier&amp;nbsp;<br />else&amp;nbsp;@name&amp;nbsp;end&amp;nbsp;<br /><br />end&amp;nbsp;<br /><br />end&amp;nbsp;<br /><br />fetch&amp;nbsp;next&amp;nbsp;from&amp;nbsp;syscolumns_cursor&amp;nbsp;into&amp;nbsp;@name,@xtype&amp;nbsp;<br /><br />end&amp;nbsp;<br /><br />close&amp;nbsp;syscolumns_cursor&amp;nbsp;<br />deallocate&amp;nbsp;syscolumns_cursor&amp;nbsp;<br /><br />set&amp;nbsp;@sql=&#39;set&amp;nbsp;nocount&amp;nbsp;on&amp;nbsp;sel&#101;ct&amp;nbsp;&#39;&#39;ins&#101;rt&amp;nbsp;&#39;+@tablename+&#39;(&#39;+@column+&#39;)&amp;nbsp;values(&#39;&#39;as&amp;nbsp;&#39;&#39;–&#39;&#39;,&#39;+@columndata+&#39;,&#39;&#39;)&#39;&#39;&amp;nbsp;from&amp;nbsp;&#39;+@tablename&amp;nbsp;<br /><br />print&amp;nbsp;&#39;–&#39;+@sql&amp;nbsp;<br />exec(@sql)&amp;nbsp;<br /><br />if&amp;nbsp;@ident&amp;nbsp;is&amp;nbsp;not&amp;nbsp;null&amp;nbsp;<br />print&amp;nbsp;&#39;SET&amp;nbsp;IDENTITY_Ins&#101;rt&amp;nbsp;&#39;+@TableName+&#39;&amp;nbsp;OFF&#39;&amp;nbsp;<br /><br />GO<br /><br />exec&amp;nbsp;UspOutputData&amp;nbsp;你的表名<br />

如何制作数据库安装程序

Dlg_SetupDatabase://安装数据库的界面

szMsg=&#34;请选择应用程序安装类型&#34;;

szTitle=&#34;应用程序安装类型&#34;;

SetupDatabase=&#34;服务器端&#34;;

noSetupDatabase=&#34;客户端&#34;;

svCheck1=TRUE;

svCheck2=FALSE;

nResult=AskOptions(EXCLUSIVE,szMsg,SetupDatabase,svCheck1,

noSetupDatabase,svCheck2);

if nResult=BACK goto Dlg_SdRegisterUserEx;

if svCheck1=TRUE then

goto Dlg_SdShowDlgEdit3;

endif;

//modify by sds

//if svCheck2=TRUE goto Dlg_SdAskDestPath;

if svCheck2=TRUE goto Dlg_SdShowDlgEdit3;

Dlg_SdShowDlgEdit3:

szTitle=&#34;请输入数据库信息&#34;;

szMsg=&#34;请输入数据库信息&#34;;

ServerName=&#34;服务器名称&#34;;

UserName=&#34;用户名称&#34;;

Password=&#34;数据库口令&#34;;

svEdit1=&#34;&#34;;

svEdit2=&#34;sa&#34;;

svEdit3=&#34;&#34;;

nResult=SdShowDlgEdit3(szTitle,szMsg,ServerName,UserName,

Password,svEdit1,svEdit2,svEdit3);

//这个地方要产生一个脚本文件Cr&#101;ateDatabase.Sql;

//if (nResult=BACK) goto Dlg_SetupDatabase;

if (nResult=BACK) then

goto Dlg_SetupDatabase;

else

WriteProfString (WINSYSDIR^&#34;DbInfo.ini&#34;, &#34;DatabaseInfo&#34;, &#34;ServerName&#34;,svEdit1);

WriteProfString (WINSYSDIR^&#34;DbInfo.ini&#34;, &#34;DatabaseInfo&#34;, &#34;UserName&#34;,svEdit2);

WriteProfString (WINSYSDIR^&#34;DbInfo.ini&#34;, &#34;DatabaseInfo&#34;, &#34;PassWord&#34;,svEdit3);

if (svCheck2=TRUE) goto Dlg_SdAskDestPath;

if svCheck1=TRUE then

OpenFileMode(FILE_MODE_APPEND);

Cr&#101;ateFile(DataBaseHandle,WINSYSDIR,&#34;CheckDataBaseInfo.Bat&#34;);

//dbCheck.Sql--应该是我们自己带的SRCDIR^

CheckDataBaseJbStr=&#34;@isqlw -S %s -d master -U %s -P %s -i &#34;+SRCDIR^&#34;dbCheck.sql -o &#34;+WINSYSDIR^&#34;out2.txt&#34;;

Sprintf(CheckDataBaseJbStr,CheckDataBaseJbStr,svEdit1,svEdit2,svEdit3);

WriteLine(DataBaseHandle,&#34;@echo 正在检查数据库信息请稍等…&#34;);

WriteLine(DataBaseHandle,CheckDataBaseJbStr);

CloseFile(DataBaseHandle);

LaunchAppAndWait(WINSYSDIR^&#34;CheckDataBaseInfo.Bat&#34;,&#34;&#34;,WAIT);

//写DBInfo文件让系统可以初始话BDE的配置

OpenFileMode(FILE_MODE_NORMAL);

OpenFile(OutHandle,WINSYSDIR,&#34;out2.txt&#34;);

GetLine(OutHandle,OutStr);

if OutStr=&#39;1&#39; then

MessageBox(&#34;该数据库存在,本次安装将不在安装数据库&#34;,WARNING);

CloseFile(OutHandle);

//Del&#101;teFile(WINSYSDIR^&#34;CheckDataBaseInfo.Bat&#34;);

//Del&#101;teFile(WINSYSDIR^&#34;out2.txt&#34;);

goto Dlg_SdAskDestPath;//不进行选择数据库的安装了

endif;

endif;

endif;

/*else

*/

//增加一个公司标示界面来插入数据—这个界面要负责产生Ins&#101;rtCompInfo.sql文件,让安装数据库的时候调用

Dlg_SdShowDlgEdit2:

szTitle=&#34;请输入公司信息&#34;;

szMsg=&#34;请输入公司信息&#34;;

CompName=&#34;公司名称&#34;;

CompInfo=&#34;系统标识&#34;;

nResult=SdShowDlgEdit2(szTitle,szMsg,CompName,CompInfo,

CompNameStr,CompInfoStr);

if (nResult)=BACK then

goto Dlg_SdShowDlgEdit3;

else

OpenFileMode(FILE_MODE_APPEND);

Cr&#101;ateFile(CompHandle,WINSYSDIR,&#34;Ins&#101;rtCompInfo.sql&#34;);

CompStr=&#34;ins&#101;rt into XTBZ(XTDM,XTMC) values(&#34;+&#34;&#39;&#34; +&#34;%s&#34;+

&#34;&#39;&#34;+&#34;,&#39;&#34;+&#34;%s&#34;+&#34;&#39;) &#34;;

Sprintf(CompStr,CompStr,CompNameStr,CompInfoStr);

WriteLine(CompHandle,&#34;use xs &#34;);

WriteLine(CompHandle,CompStr);

WriteLine(CompHandle,&#34;go&#34;);

CloseFile(CompHandle);

endif;

Dlg_DataBase: //选择安装数据库

szMsg=&#34;请选择数据库安装路径&#34;;

szTitle=&#34;数据库安装程序&#34;;

svDestDir=&#34;C:&#34;;

nResult=AskDestPath (&#34;数据库文件路径&#34;, szMsg, svDestDir, 0);

//写文件

if (nResult=BACK) then

goto Dlg_SdShowDlgEdit2;

else

if GetDiskSpace(svDestDir)<10485760 then

MessageBox(&#34;磁盘空间太少了&#34;,WARNING);

goto Dlg_DataBase;

else

/*if (ExistsDir(svDestDir+&#34;Data&#34;))!=EXISTS then

Cr&#101;ateDir(svDestDir+&#34;Data&#34;);

endif;*/

Cr&#101;ateDir(svDestDir+&#34;Data&#34;);

//写批处理文件了创建数据库,svEdit1,是服务器名称svEdit2,是用户名称,svEdit3是数据库密码

//先要写创建数据库的脚本文件

OpenFileMode (FILE_MODE_APPEND);

Cr&#101;ateFile(DataBaseHandle,WINSYSDIR,&#34;Cr&#101;ateDatabase.Sql&#34;);

// Sprintf

CDataBaseSql=&#34;Cr&#101;ate DATABASE xs &#34;+

&#34; ON &#34;+

&#34;( NAME = xs_dat&#34;+&#34;, &#34;

+&#34; FILENAME=&#34;+&#34;&#39;&#34;+&#34;%s&#34;+&#34;&#39;&#34;

+&#34; )LOG ON (NAME=xs_log&#34;+

&#34;,FileName=&#34;+&#34;&#39;&#34;+&#34;%s&#34;+&#34;&#39;&#34;

+&#34;)&#34;;

LogFileName=svDestDir+&#34;Data&#34;+&#34;xs_log.ldf&#34;;

DataBaseFileName=svDestDir+&#34;Data&#34;+&#34;xs_dat.mdf&#34;;

Sprintf(DataBaseMsg,CDataBaseSql,DataBaseFileName,LogFileName);

WriteLine(DataBaseHandle,DataBaseMsg);

CloseFile(DataBaseHandle);

OpenFileMode(FILE_MODE_APPEND);

Cr&#101;ateFile(DataBaseHandle,WINSYSDIR,&#34;ExecuteSql.Bat&#34;);

//dbCheck.Sql--应该是我们自己带的SRCDIR^

CheckDataBaseJbStr=&#34;@isqlw -S %s -d master -U %s -P %s -i &#34;+WINSYSDIR^&#34;Cr&#101;ateDatabase.Sql -o &#34;+WINSYSDIR^&#34;out1.txt&#34;;

TableXsStr=&#34;@isqlw -S %s -d master -U %s -P %s -i &#34;+SRCDIR^&#34;Table_xs.Sql -o &#34;+WINSYSDIR^&#34;out1.txt&#34;;

CompStr=&#34;@isqlw -S %s -d master -U %s -P %s -i &#34;+WINSYSDIR^&#34;Ins&#101;rtCompInfo.sql -o &#34;+WINSYSDIR^&#34;out1.txt&#34;;

Sprintf(CheckDataBaseJbStr,CheckDataBaseJbStr,svEdit1,svEdit2,svEdit3);

Sprintf(TableXsStr,TableXsStr,svEdit1,svEdit2,svEdit3);

Sprintf(CompStr,CompStr,svEdit1,svEdit2,svEdit3);

WriteLine(DataBaseHandle,&#34;@echo 正在创建数据库请稍等…&#34;);

WriteLine(DataBaseHandle,CheckDataBaseJbStr); //创建数据库

WriteLine(DataBaseHandle,&#34;@echo 正在更新脚本语言请稍等…&#34;);

WriteLine(DataBaseHandle,TableXsStr);//写Table_xs的文件;

WriteLine(DataBaseHandle,&#34;@echo 正在插入公司信息请稍等…&#34;);

WriteLine(DataBaseHandle,CompStr);//插入公司标示

CloseFile(DataBaseHandle);

LaunchAppAndWait(WINSYSDIR^&#34;ExecuteSql.Bat&#34;,&#34;&#34;,WAIT);

Del&#101;teFile(WINSYSDIR^&#34;Cr&#101;ateDatabase.Sql&#34;);

Del&#101;teFile(WINSYSDIR^&#34;Ins&#101;rtCompInfo.sql&#34;);

Del&#101;teFile(WINSYSDIR^&#34;ExecuteSql.Bat&#34;);

Del&#101;teFile(WINSYSDIR^&#34;out1.txt&#34;);

MessageBox(&#34;恭喜数据库安装成功&#34;,INFORMATION);

endif;

endif;

上面的是通过脚本来完成的!(对InstallSheild脚本熟悉的人应该能看懂)

谈谈数据从sql server数据库导入mysql数据库的体验

因工作需要,要将存放在sql server数据库中的数据全部导入到mysql数据库中,在网上搜集相关资料,找到两种方法,现在分别谈谈对他们的看法。

第一种是安装mysql ODBC,利用sql server的导出功能,选择mysql数据源,进行数据的直接导出,这种方法很简便,但是针对实际应用有很多弊端,最主要体现就是数据类型问题,首先,sql server数据库中

的ntext,image等数据类型的数据无法直接写入到mysql数据库中,据说只要稍加改动就可以,可惜偶这只菜鸟还没想到如何改动,其次,因为偶在mysql中的数据库设计中将时间都设成int型(保存的是时间戳),所以在数据导过来后,就会出现冲突,再次,这种方法生成的mysql数据表的字段类型都不很合适,所以此种方法我觉得不能提倡。

第二种是利用php或asp脚本来实现数据的导入功能,这种方法需要编写程序,但灵活性大,操作也不是那么困难,一切都尽在你的掌握之中,现简单介绍一下该方法

前提条件是你的mysql环境已经搭建好了,先建好目标数据库,再将所有的表结构用sql语句生成,现在万事具备,只缺数据了。

可以通过下面的php脚本来实现sql server中mydb数据库的user表中数据向mysql中mydb数据库导入

&amp;lt;?

$cnx = odbc_connect(&#39;web&#39;, &#39;admin&#39;, &#39;123456&#39;);//&#39;web&#39;是sqlserver中mydb的数据源名,&#39;admin&#39;是访问mydb的用户名,&#39;123456&#39;是访问mydb的密码

$cur= odbc_exec( $cnx, &#39;sel&#101;ct * from user&#39; );//打开sql server中mydb数据库的user表

$num_row=0;

$conn=mysql_pconnect(&#34;localhost&#34;,&#34;root&#34;,&#34;123456&#34;);// 连接mysql

@mysql_sel&#101;ct_db(&#39;mydb&#39;,$conn) o&#114;

die(&#34;无法连接到数据库,请与管理员联系!&#34;);//打开mysql的mydb数据库

while( odbc_fetch_row( $cur )) //从sql server的mydb库中的user表逐条取出数据,如果对数据进行选择,可在前面的sel&#101;ct语句中加上条件判断

{

$num_row++;

$field1 = odbc_result( $cur, 1 ); // 这里的参数i(1,2,3..)指的是记录集中的第i个域,你可以有所选择地进行选取,fieldi得到对应域的值,然后你可以对fieldi进行操作

$field2 = odbc_result( $cur, 2 );

$field3 = odbc_result( $cur, 3 );

$field4 = odbc_result( $cur, 4 );

$field5 = odbc_result( $cur, 5 );

$field6 = odbc_result( $cur, 6 );

$field5 = timetoint($field5); //这里是对sql server中的datetime类型的字段进行相应转换处理,转换成我所需要的int型

$querystring = &#34;ins&#101;rt into user

(id,name,username,password,recdate)

values(&#39;$field1&#39;,&#39;$field2&#39;,&#39;$field3&#39;,&#39;$field4&#39;,&#39;$field5&#39;)&#34; ;

mysql_query($querystring,$conn);

}

function timetoint($str){

$arr1=split(&#34; &#34;,$str);

$datestr=$arr1[0];

$timestr=$arr1[1];

$arr_date=split(&#34;-&#34;,$datestr);

$arr_time=split(&#34;:&#34;,$timestr);

$year=$arr_date[0];

$month=$arr_date[1];

$day=$arr_date[2];

$hour=$arr_time[0];

$minute=$arr_time[1];

$second=$arr_time[2];

$time_int=mktime($hour,$minute,$second,$month,$day,$year);

return $time_int;

}

?&amp;gt;

将该段脚本存成sql.php,在服务器上执行,就可以将服务器上sql server中mydb数据库的user表中的数据导入到mysql中mydb数据库的user表中去。其他表的操作与此雷同,就不赘述了。

下面再介绍一下asp脚本实现sql server中mydb数据库的数据向mysql中mydb数据库导入

&amp;lt;%

set conn=server.cr&#101;ateobject(&#34;adodb.connection&#34;)

conn.open &#39;web&#39;, &#39;admin&#39;, &#39;123456&#39; // &#39;web&#39;是sqlserver中mydb的数据源名,&#39;admin&#39;是访问mydb的用户名,&#39;123456&#39;是访问mydb的密码

set rs=server.cr&#101;ateobject(&#34;adodb.recordset&#34;)

sql=&#34;sel&#101;ct ID,name,username,password,datediff(s,&#39;1970-01-01 00:00:00&#39;,recdate)-8*3600,reid,filename,fileContentType,filevalue from senddate&#34; //这条sql语句实现了将datetime类型的recdate字段转化成unix时间戳的int型

rs.open sql,conn,1,3

set conn1=server.cr&#101;ateobject(&#34;adodb.connection&#34;)

conn1.open &#34;myoa&#34;,&#34;root&#34;,&#34;q1-d6=7?&#34;

i=1

do while not rs.eof

field1 = rs(0)

field2 = rs(1)

field3 = rs(2)

field4 = rs(3)

field5 = rs(4)

sql1 = &#34;ins&#101;rt into user(ID,name,username,password,recdate)

values(&#34;&amp;field1&amp;&#34;,&#39;&#34;&amp;field2&amp;&#34;&#39;,&#39;&#34;&amp;field3&amp;&#34;&#39;,&#39;&#34;&amp;field4&amp;&#34;&#39;,&#34;&amp;field5&amp;&#34;)&#34;

conn1.execute sql1

rs.movenext

i=i+1

loop

rs.close

set rs=nothing

conn.close

set conn=nothing

conn1.close

set conn1=nothing

%&amp;gt;

以上两个是分别采用php脚本和asp脚本对user表的数据进行由sql server到mysql的导入其间我采用2种回避的方法来避免ntext,image类型数据的传递,一种是将ntext字段改为nvarchar(4000),因为实际情况,原始数据中该字段的数据长度都未超过4000个字,所以并没有出现数据截断,另一个手段是将image类型数据取出来写到文件中,以文件形式保存,将文件路径存到数据库中,方法见下:

function makeattach(fileContentType,filevalue,i)

sel&#101;ct case fileContentType

case &#34;application/msword&#34;

ext=&#34;doc&#34;

case &#34;application/vnd.ms-excel&#34;

ext=&#34;exl&#34;

case &#34;application/vnd.ms-powerpoint&#34;

ext=&#34;pps&#34;

case &#34;application/x-rar-compressed&#34;

ext=&#34;rar&#34;

case &#34;application/x-zip-compressed&#34;

ext=&#34;zip&#34;

case &#34;image/gif&#34;

ext=&#34;gif&#34;

case &#34;image/pjpeg&#34;

ext=&#34;jpg&#34;

case &#34;text/plain&#34;

ext=&#34;txt&#34;

case else

ext=&#34;x&#34;

end sel&#101;ct

if ext&amp;lt;&amp;gt;&#34;x&#34; then

set fso=server.cr&#101;ateobject(&#34;FileSystemObject&#34;)

fName=&#34;attech&#34;&amp;i&amp;&#34;.&#34;&amp;ext

Dir=&#34;d:attach&#34;

If fso.FileExists(Dir &amp; fName) Then fso.del&#101;tefile Dir &amp; fName

If fName&amp;lt;&amp;gt;&#34;&#34; AND NOT fso.FileExists(Dir &amp; fName) Then

Set strm1=Server.Cr&#101;ateObject(&#34;ADODB.Stream&#34;)

strm1.Open

strm1.Type=1 &#39;Binary

strm1.Write filevalue

strm1.SaveToFile Dir &amp; fName,2

Set strm1=Nothing

end if

makeattach=fName

end if

end function

这个函数有3个输入参数,第一个是文件的contentType,第二个是文件的二进制数值,第三个是个可以区别文件名的变量,先根据contentType确定所存文件的后缀名,然后就是将二进制数值保存成指定文件名的文件,并将文件名作为输出参数返回,将返回的参数作为数据写到mysql的数据库中保存。

时间匆忙,先总结到这里,希望这些文字能对有需要的人有些帮助,少走些弯路,感谢您的阅读。:)

SQL SERVER日志清除的两种方法(命令行)

<p>最好的方法:</p>

<p>backup log database_name with no_log dbcc shrinkfile (database_name_log,truncateonly)</p>

<p>&amp;nbsp;</p>

<p>&amp;nbsp;</p>

<p>&amp;nbsp;</p>

<p>方法一</p>

<p>一般情况下,SQL数据库的收缩并不能很大程度上减小数据库大小,其主要作用是收缩日志大小,应当定期进行此操作以免数据库日志过大<br />1、设置数据库模式为简单模式:打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server–&amp;gt;SQL Server组–&amp;gt;双击打开你的服务器–&amp;gt;双击打开数据库目录–&amp;gt;选择你的数据库名称(如论坛数据库Forum)–&amp;gt;然后点击右键选择属性–&amp;gt;选择选项–&amp;gt;在故障还原的模式中选择&amp;ldquo;简单&amp;rdquo;,然后按确定保存<br />2、在当前数据库上点右键,看所有任务中的收缩数据库,一般里面的默认设置不用调整,直接点确定<br />3、收缩数据库完成后,建议将您的数据库属性重新设置为标准模式,操作方法同第一点,因为日志在一些异常情况下往往是恢复数据库的重要依据</p>

<p>方法二</p>

<p>SET NOCOUNT ON<br />DECLARE @LogicalFileName sysname,<br />@MaxMinutes INT,<br />@NewSize INT<br /></p>

<p>USE tablename — 要操作的数据库名<br />Sel&#101;ct @LogicalFileName = &#39;tablename_log&#39;, — 日志文件名<br />@MaxMinutes = 10, — Limit on time allowed to wrap log.<br />@NewSize = 1 — 你想设定的日志文件的大小(M)</p>

<p>– Setup / initialize<br />DECLARE @OriginalSize int<br />Sel&#101;ct @OriginalSize = size <br />FROM sysfiles<br />Wh&#101;re name = @LogicalFileName<br />Sel&#101;ct &#39;Original Size of &#39; + db_name() + &#39; LOG is &#39; + <br />CONVERT(VARCHAR(30),@OriginalSize) + &#39; 8K pages o&#114; &#39; + <br />CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + &#39;MB&#39;<br />FROM sysfiles<br />Wh&#101;re name = @LogicalFileName<br />Cr&#101;ate TABLE DummyTrans<br />(DummyColumn char (8000) not null)<br /></p>

<p>DECLARE @Counter INT,<br />@StartTime DATETIME,<br />@TruncLog VARCHAR(255)<br />Sel&#101;ct @StartTime = GETDATE(),<br />@TruncLog = &#39;BACKUP LOG &#39; + db_name() + &#39; WITH TRUNCATE_ONLY&#39;</p>

<p>DBCC SHRINKFILE (@LogicalFileName, @NewSize)<br />EXEC (@TruncLog)<br />– Wrap the log if necessary.<br />WHILE @MaxMinutes &amp;gt; DATEDIFF (mi, @StartTime, GETDATE()) — time has not expired<br />AND @OriginalSize = (Sel&#101;ct size FROM sysfiles Wh&#101;re name = @LogicalFileName) <br />AND (@OriginalSize * 8 /1024) &amp;gt; @NewSize <br />BEGIN — Outer loop.<br />Sel&#101;ct @Counter = 0<br />WHILE ((@Counter &amp;lt; @OriginalSize / 16) AND (@Counter &amp;lt; 50000))<br />BEGIN — up&#100;ate<br />Ins&#101;rt DummyTrans VALUES (&#39;Fill Log&#39;) <br />Del&#101;te DummyTrans<br />Sel&#101;ct @Counter = @Counter + 1<br />END <br />EXEC (@TruncLog) <br />END <br />Sel&#101;ct &#39;Final Size of &#39; + db_name() + &#39; LOG is &#39; +<br />CONVERT(VARCHAR(30),size) + &#39; 8K pages o&#114; &#39; + <br />CONVERT(VARCHAR(30),(size*8/1024)) + &#39;MB&#39;<br />FROM sysfiles <br />Wh&#101;re name = @LogicalFileName<br />Dro&#112; TABLE DummyTrans<br />SET NOCOUNT OFF </p>

<p>方法1:<br />第一步:<br />backup log database_name with no_log <br />或者 backup log database_name with truncate_only –no_log和truncate_only是在这里是同义的,随便执行哪一句都可以<br />第二步:<br />1.收缩特定数据库的所有数据和日志文件,执行 dbcc shrinkdatabase (database_name,[,target_percent])–database_name是要收缩的数据库名称;target_percent是数据库收缩后的数据库文件中所要的剩余可用空间百分比<br />2.收缩一次一个特定数据库中的数据或日志文件,执行 dbcc shrinkfile(file_id,[,target_size]) –file_id是要收缩的文件的标识 (ID) 号,若要获得文件 ID,请使用 FILE_ID 函数或在当前数据库中搜索 sysfiles;target_size是用兆字节表示的所要的文件大小(用整数表示)。如果没有指定,dbcc shrinkfile 将文件大小减少到默认文件大小</p>

<p>两个dbcc都可以带上参数notruncate或truncateonly,具体意思看帮助。<br /></p>

<p> </p>

<p>方法2(这个方法在sqlserver2000的环境下做一般能成功,在sqlserver7及以下版本就不一定了): <br />第一步: <br />先备份整个数据库以备不测<br />第二步: <br />备份结束后,在Query Analyzer中执行如下的语句: <br />exec sp_detach_db yourDBName,true –卸除这个DB在MSSQL中的注册信息 <br />第三步: <br />到日志的物理文件所在的目录中去删除该日志文件或者将该日志文件移出该目录 <br />第四步: <br />在Query Analyzer中执行如下的语句: <br />exec sp_attach_single_file_db yourDBName,&#39;d:mssql7datayourDBName_data.mdf&#39; <br />–以单文件的方式注册该DB,如果成功则MSSQL将自动为这个DB生成一个500K的日志文件。</p>

<p>以上方法在清除log日志中均有效。<br />但,能否让sql server 不产生log日志呢?以上方法好像均无效。 </p>

<p>我这儿正好有个case:<br />我客户的sql server每天都会产生4,500M的log日志,每天都清除一下,非常不便。有没有办法实现不产生log日志呢?</p>

<p>我分析了一下客户产生log日志的原因,并且做了相应测试。<br />客户是每天将数据库清空,从总系统中将数据导入到sql server里。我感决sqlserver在插入时产生log不大,在del&#101;te整个库时产生log极大。<br />比如:<br />Sel&#101;ct * into test_2 from b_bgxx<br />共45000条记录,产生十几M log,如果<br />del&#101;te from test_2<br />产生80多M log ,这明显存在问题。</p>

<p>虽然可以换成:<br />truncate table test_2<br />但我还是希望能找到不产生log的方法。就如oracle不产生归档一样。 </p>

更改数据库中表的所属用户的两个方法

<p>–更改某个表<br />exec sp_changeobjectowner &#39;tablename&#39;,&#39;dbo&#39;<br /></p>

<p>–存储更改全部表<br />Cr&#101;ate PROCEDURE dbo.User_ChangeObjectOwnerBatch<br />@OldOwner as NVARCHAR(128),<br />@NewOwner as NVARCHAR(128)<br />AS</p>

<p>DECLARE @Name as NVARCHAR(128)<br />DECLARE @Owner as NVARCHAR(128)<br />DECLARE @OwnerName as NVARCHAR(128)</p>

<p>DECLARE curObject CURSOR FOR <br />sel&#101;ct &#39;Name&#39; = name,<br />&#39;Owner&#39; = user_name(uid)<br />from sysobjects<br />wh&#101;re user_name(uid)=@OldOwner<br />order by name</p>

<p>OPEN curObject<br />FETCH NEXT FROM curObject INTO @Name, @Owner<br />WHILE(@@FETCH_STATUS=0)<br />BEGIN <br />if @Owner=@OldOwner <br />begin<br />set @OwnerName = @OldOwner + &#39;.&#39; + rtrim(@Name)<br />exec sp_changeobjectowner @OwnerName, @NewOwner<br />end<br />– sel&#101;ct @name,@NewOwner,@OldOwner</p>

<p>FETCH NEXT FROM curObject INTO @Name, @Owner<br />END</p>

<p>close curObject<br />deallocate curObject<br /></p>

<p>GO </p>

缩小SQL Server数据库日志

–缩小日志

– exec p_compdb ’test’

cr&#101;ate proc p_compdb

@dbname sysname, –要压缩的数据库名

@bkdatabase bit=1, –因为分离日志的步骤中,可能会损坏数据库,所以你可以选择是否自动数据库

@bkfname nvarchar(260)=’’ –备份的文件名,如果不指定,自动备份到默认备份目录,备份文件名为:数据库名+日期时间

as

–1.清空日志

exec(’DUMP TRANSACTION [’+@dbname+’] WITH NO_LOG’)

–2.截断事务日志:

exec(’BACKUP LOG [’+@dbname+’] WITH NO_LOG’)

–3.收缩数据库文件(如果不压缩,数据库的文件不会减小

exec(’DBCC SHRINKDATABASE([’+@dbname+’])’)

–4.设置自动收缩

exec(’EXEC sp_dboption ’’’+@dbname+’’’,’’autoshrink’’,’’TRUE’’’)

–后面的步骤有一定危险,你可以可以选择是否应该这些步骤

–5.分离数据库

if @bkdatabase=1

begin

if isnull(@bkfname,’’)=’’

set @bkfname=@dbname+’_’+convert(varchar,getdate(),112)

+replace(convert(varchar,getdate(),108),’:’,’’)

sel&#101;ct 提示信息=’备份数据库到SQL 默认备份目录,备份文件名:’+@bkfname

exec(’backup database [’+@dbname+’] to disk=’’’+@bkfname+’’’’)

end

–进行分离处理

cr&#101;ate table #t(fname nvarchar(260),type int)

exec(’ins&#101;rt into #t sel&#101;ct filename,type=status&amp;0×40 from [’+@dbname+’]..sysfiles’)

exec(’sp_detach_db ’’’+@dbname+’’’’)

–删除日志文件

declare @fname nvarchar(260),@s varchar(8000)

declare tb cursor local for sel&#101;ct fname from #t wh&#101;re type=64

open tb

fetch next from tb into @fname

while @@fetch_status=0

begin

set @s=’del &#34;’+rtrim(@fname)+’&#34;’

exec master..xp_cmdshell @s,no_output

fetch next from tb into @fname

end

close tb

deallocate tb

–附加数据库

set @s=’’

declare tb cursor local for sel&#101;ct fname from #t wh&#101;re type=0

open tb

fetch next from tb into @fname

while @@fetch_status=0

begin

set @s=@s+’,’’’+rtrim(@fname)+’’’’

fetch next from tb into @fname

end

close tb

deallocate tb

exec(’sp_attach_single_file_db ’’’+@dbname+’’’’+@s)

GO

返回顶部