小弟在一些商业软件上看到它们在安装过程中会出现一个输入框让用户填入服务器名称和帐户以及密码,然后点确定后就会将该创建该软件的数据库;或者,在安装完毕后一般都会提供一个小工具让用户同样输入服务器名称和帐户以及密码后创建数据库,甚至还初始化了一些数据。
我对这方面的设计有一点模糊。
第一,这个工具是否在调用执行一个数据文件里的Sql语句从而创建了数据库?
第二,这个工具是否通过调用SQLSERVER一个工具(好像是BCP.EXE,我也不是很清楚)来调用SQl脚本文件,但是这样的话,请问对于用户输入的服务器名称和帐户以及密码是怎样赋值呢?包括程序中是怎样调用该SQL的工具来执行呢?
另外,小弟还有一个疑问,在创建数据库时,Ado控件是不是必须连接到Master数据库上?
 
由于我想做一个这样能够创建SQLServer数据库的工具(创建的同时也能够导入一些初始数据)。
请高手解答以上问题的,并指点思路,小弟不胜感激!
问题解决另外再送300

解决方案 »

  1.   

    EXEC sp_attach_db @dbname = N'pubs', 
       @filename1 = N'c:\Program Files\Microsoft SQL Server\MSSQL\Data\pubs.mdf', 
       @filename2 = N'c:\Program Files\Microsoft SQL Server\MSSQL\Data\pubs_log.ldf'
      

  2.   

    你可做一个小程序,执行上面的存储过程 sp_attach_db就可以了,在安装的时候,你就启动你的这个小程序进行数据库的注册。
      

  3.   

    To wyb716(小刀):
    照你的说法,存储过程放在哪里!因为客户机上的SQLSERVER上是不可能存放该存储过程的,假如我要创建的数据库是Temp,同时里面也包含几十张表。而且,执行存储过程也必须连接到服务器上,那么,就我刚才的说法,ADO连接对象应该连接到服务器哪里?
    照你的说法,好像不是创建,而是执行存在的数据库注册,是不是这样的?
      

  4.   

    连接服务器上的Master数据库或者其它的如pubs数据库
      

  5.   

    照你的说法,执行存储是不是存放在Master数据库或者其它的如pubs数据库?
    这样的话就无法实现这个程序功能了,因为客户机上的SQLSERVER上是不可能存在这个存储过程的!
    还有我上面的第二个问题到底是那个说法呢
    >>“照你的说法,好像不是创建,而是执行存在的数据库注册,是不是这样的?”
      

  6.   

    我们在用SQL server为后端数据库时,由于装原因,用户可能不会附加数库。一般在初始化时进行创建数据库,先创建数据库,然后再创建表或是存储过程等。这里只给你一个表做例子。procedure Tmain.greatedatabase;
    var
        Acurentmdfpath,Acurentlogpath:string;
    begin
    Acurentmdfpath:=Extractfilepath(application.exeName)+'data\temp.mdf';
    Acurentlogpath:=Extractfilepath(application.exeName)+'data\temp.ldf';
    createQuery.SQL.Clear;
    createQuery.SQL.Add('CREATE DATABASE temp ON ( NAME = temp_dat,FILENAME ='''+Acurentmdfpath+''') LOG ON( NAME = temp_log,FILENAME ='''+Acurentlogpath+''')');
    createQuery.ExecSQL;
    createQuery.ConnectionString:='Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=temp;Data Source=127.0.0.1';
    createQuery.SQL.Clear;
    createQuery.SQL.Add('CREATE TABLE [dbo].[bj_inf] ( [id] [int] IDENTITY (1, 1) NOT NULL ,'+
    '[Bj_zyfx_id] [char] (4) COLLATE Chinese_PRC_CI_AS NOT NULL ,'+
    '[Bj_name] [char] (40) COLLATE Chinese_PRC_CI_AS NULL ,'+
    '[Bj_rxn] [char] (4) COLLATE Chinese_PRC_CI_AS NULL ,'+
    '[Bj_xzn] [char] (6) COLLATE Chinese_PRC_CI_AS NULL ,'+
    '[Bj_s] [char] (2) COLLATE Chinese_PRC_CI_AS NULL ,'+
    '[bj_rxy] [char] (2) COLLATE Chinese_PRC_CI_AS NULL ,'+
    '[bj_bz] [text] COLLATE Chinese_PRC_CI_AS NULL ,'+
    '[bj_xz] [char] (10) COLLATE Chinese_PRC_CI_AS NULL) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]');
    createQuery.ExecSQL;
      

  7.   

    其实动态创建数据库是很费时的,用我上面说的存储过程来完成是完全可行的,一般在安装时,你只要把你的数据库文件进行打包,在安装完数据库文件之后,采用ADO连接到你的后端服务器,执行就行了。如下所示:
      if ADOConnection1.Connected then ADOConnection1.Connected := false;
      ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;DataSource=后端服务器'+
        'User ID=你输入的用户名;Password=你输入的密码;Persist Security Info=True';
      ADOConnection1.Execute('EXEC sp_attach_db @dbname = N''数据库名'','+
        '@filename1 = N''数据库文件'','+
        '@filename2 = N''数据库日志文件''');
    如果你要动态创建数据库的话,也可以的,如下所示:
      if ADOConnection1.Connected then ADOConnection1.Connected := false;
      ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;DataSource=后端服务器'+
        'User ID=你输入的用户名;Password=你输入的密码;Persist Security Info=True';
      ADOConnection1.Execute('创建数据库的语句');
      ADOConnection1.Execute('EXEC sp_attach_db @dbname = N''数据库名'','+
        '@filename1 = N''数据库文件'','+
        '@filename2 = N''数据库日志文件''');
    要先创建,然后注册
      

  8.   

    直接使用ADO使用基本得语句就可以实现,以前我用ADO+VB写过一个类。
    另外可以考虑使用SQLDMO实现,操作更方便一些
      

  9.   

    wyb716(小刀)的的方法很好!能够满足我的要求!但是我也想知道qs1976(曾青松) 关于SQLDMO的方法,请qs1976(曾青松) 指点一下!
    第二,如果我想在程序中执行SQL脚本文件而不用查询分析器,代码中应该怎样写呢?
    *********************************************************************************还有,我已经另外开辟了一个简单的问题:“怎样在程序中设置某个目录为IIS的默认目录?”了解的大虾请告知!
    相关连接
    http://expert.csdn.net/Expert/topic/1667/1667282.xml?temp=4.912966E-02
      

  10.   

    这有个执行SQL脚本的例子,
    通过调用外部程序SQLSERVER的osql.exe来实现,调用时隐藏osql.exe的窗口
    ====================================================================
    unit UtManageData;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons,shellApi, ExtCtrls, DB, ADODB, Grids, DBGrids,ComObj;type
      TFrmManageData = class(TForm)
        GroupBox2: TGroupBox;
        Label3: TLabel;
        meoInfo: TMemo;
        bbtnCreate: TBitBtn;
        bbtnExit: TBitBtn;
        Image1: TImage;
        AdoCon: TADOConnection;
        DataSource1: TDataSource;
        ADOQuery1: TADOQuery;
        cbServer: TComboBox;
        GroupBox1: TGroupBox;
        Label1: TLabel;
        edtUser: TEdit;
        Label2: TLabel;
        edtPassWord: TEdit;
        Bevel1: TBevel;
        procedure bbtnCreateClick(Sender: TObject);
        procedure FormActivate(Sender: TObject);
        procedure bbtnExitClick(Sender: TObject);  private
        function createDatabase(server,user,passWord : string) : boolean;
        procedure ExecuteOSql(server,user,passWord : string);
        procedure getNetWorkServer;
        { Private declarations }
      public
        { Public declarations }
      end;var
      FrmManageData: TFrmManageData;implementation//uses UtSelectServer;{$R *.dfm}procedure TFrmManageData.bbtnCreateClick(Sender: TObject);
    var
      server,user,passWord : string;
    begin
     server := cbServer.Text;
     user    := edtUser.Text;
     passWord :=edtPassWord.Text;
        
    if createDatabase(server,user,passWord) then   //创建数据库
     begin
          ExecuteOSql(server,user,passWord);  //执行sql脚本创建表
     endend;procedure TFrmManageData.FormActivate(Sender: TObject);
    begin
      getNetWorkServer; //获得服务器
    end;procedure TFrmManageData.bbtnExitClick(Sender: TObject);
    begin
      Close;
    end;function TFrmManageData.createDatabase(server,user,passWord : string): boolean;
    var
      sqlStr : String;
      conStr : String;
      year,month,day : Word;
    begin
       decodeDate(now,year,month,day);
      //Provider=SQLOLEDB.1;Password=ssss;Persist Security Info=True;User ID=sa;Data Source=ZBDI
     //连接数据库
      conStr :='Provider=SQLOLEDB.1;Password='+passWord+';Persist Security Info=False;User ID='+user+';';
      constr := conStr + 'Data Source='+server;
      try
        ADOCon.Close;
        ADOCon.ConnectionString  := conStr;
        ADOCon.ConnectionTimeout := 15;
        ADOCon.Connected := True;
      except    Application.MessageBox('无法建立连接,请确认数据库服务器、用户名、密码是否正确。','警告',MB_ICONWARNING);
        result := False;
        exit;
      end;
          //查找该数据库是否存在
        sqlStr := 'select name from master..sysdatabases where name='+''''+'wz'+intToStr(year)+'''';
        try
          with ADOQuery1 do
          begin
            Close;
            Connection := ADOCon;
            Sql.Add(sqlStr);
            Active := True;
            if RecordCount >0 then
            begin
              Application.MessageBox('该数据库已经存在.','警告',MB_ICONWARNING);
              result := False;
              exit;
            end;
          end;
        except
          Application.MessageBox('无法创建数据库,请确认是否正确安装。','警告',MB_ICONWARNING);
          result := False;
          exit;
        end;
          //创建数据库
      try
        with ADOquery1 do
        begin
           Close;
           Sql.clear;
           Sql.Add('Create DataBase '+'wz'+inttostr(year));
           ExecSql;
        end;
      except
         Application.MessageBox('无法创建数据库,请确认是否正确安装。','警告',MB_ICONWARNING);
         result := False;
         exit;
      end;
      result := True;
     /////end;procedure TFrmManageData.ExecuteOSql(server,user,passWord : string);
    var
      dosStr : String;
      fileName : String;
      year,month,day : Word;
    begin
      //执行 OSQl.exe
      decodeDate(now,year,month,day);
      fileName := ExtractFilePath(Application.ExeName);
      try
        dosStr := ' -S '+server+' -U '+user+' -P '+passWord+' -q '+'"use wz'+inttostr(year)+'"'+' -i '+ filename+'createDB.sql';
     //   showmessage(dosStr);
       
        shellExecute(handle,'open','osql.exe', Pchar(dosStr),nil,sw_hide);
        meoInfo.Clear;
        meoInfo.Font.Color := clred;
        meoInfo.Lines.Add('  正在创建数据库请稍后.....');
        meoInfo.Refresh;
        sleep(3000);
        meoInfo.Clear;
        meoInfo.Lines.Add('成功创建数据库。');
        Application.MessageBox('成功创建数据库。','提示',MB_ICONWARNING);
      except
        Application.MessageBox('无法创建数据库,请确认是否正确安装。','警告',MB_ICONWARNING)
      end;
    end;procedure TFrmManageData.getNetWorkServer;
    var
       SQLServer:Variant;
       ServerList:Variant;
       i,nServers:integer;
       sRetValue:String;
    begin      //获得局域网上的服务器
     try
      Application.ProcessMessages;
      SQLServer := CreateOleObject('SQLDMO.Application');
      ServerList:= SQLServer.ListAvailableSQLServers;
      nServers:=ServerList.Count;
      cbServer.Clear;
      for i := 1 to nservers do
        cbServer.Items.Add(ServerList.Item(i));
      SQLServer:=NULL;
      serverList:=NULL;
      cbServer.ItemIndex := 0;
     except
       application.MessageBox('无法找到可用的数据库服务器。','警告!',MB_ICONWARNING);
      // APPLICATION.Terminate;
     end;
    end;end.
      

  11.   

    谢谢 zhyanger() 提供的例子,问题基本上已经结束!今天我将试用以上的方法,明天结分!
    再一次谢谢大家!!!
      

  12.   

    1。可以使用开发接口或者用sql语句都能达到这个目的,至于是否另放在数据文件中随便。
    2。你可以使用sql的存储过程,数据库名等作为参数。如果是现有的数据库文件用sp_attach_db,如果是新建用sp_adddb,如果是备份文件用(忘了:)
    3。不需要。master库中的存储过程是系统自动就可以调用的。
      

  13.   

    问题已经解决!
    非常感谢wyb716(小刀)的热心解答!
    也谢谢zhyanger()对脚本的解释!
    也谢谢其他热心的网友!
    由于一个帖子只能100分,所以我只能另外开帖子送分!
    请关注!