zoukankan      html  css  js  c++  java
  • 用ADOQuery创建SQL Server数据库,并创建表结构、存储过程和视图

    昨天做系统的安装,搞这个搞到头大,现在把总结写下巴。

    PS:贴上来代码的缩进就乱掉了

    用SQL Server企业管理器导出的SQL文件是不能直接在ADOQuery里用的,因为ADOQuery不支持GO,不支持注释,视图和存储过程的创建也必须放到查询开头,所以必须要对企业管理器导出的SQL文件进行处理,才能用。

    首先,导出SQL语句

    如图设置

    注意这一步,“编写主键、外键、默认值和检查约束脚本”别忘了选。文件格式要选ANSI,因为貌似TStrings.LoadFromFile这个方法对Unicode的文本支持不好,如果你的代码不用TStringList读SQL文件,那这里选什么都无所谓。选择创建一个文件,可以确保结构按照顺序创建,免得多个文件又要搞依赖关系,分析哪个要先创建,麻烦。

    然后,创建数据库

    强烈建议将用于创建数据库和数据库结构的ADOQuery的ParamCheck属性设置为False

    (要是非要设置成True,后面莫名其妙报个错,可别怨我没拦你^_^)

    将生成的SQL文件中开头创建数据库的那部分删除(就是直到第一句use XXX这里,包含这句,也一并删除),因为创建数据库的语句我们要自己组装。

    创建数据库需要知道数据库文件和日志的存放位置(强迫用户指定貌似不太礼貌,最好自动获取到),数据库和日志文件初始大小,数据库名和排序规则。

    取数据库文件和日志存放位置的办法:(我这里是把第一个库文件的位置当做默认存放位置的)

    ADOQuery查询master库:        SELECT TOP 1 filename FROM sysaltfiles

    然后存放默认位置就是IncludeTrailingPathDelimiter(ExtractFilePath(Trim(FieldByName('filename').AsString)))

    创建数据库(仍然是在master库里执行):

            SQL.Add(Format('IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N''%s'')',[teDBName.Text]));
            SQL.Add(Format('DROP DATABASE [%s]',[teDBName.Text]));
            SQL.Add(Format(
              'CREATE DATABASE [%s] ON (NAME = N''%s_Data'', FILENAME = N''%s%s_Data.MDF'' , SIZE = 7, FILEGROWTH = 10%%) LOG ON (NAME = N''%s_Log'', FILENAME = N''%s%s_Log.LDF'' , SIZE = 7, FILEGROWTH = 10%%) COLLATE Chinese_PRC_CI_AS',
              [teDBName.Text,teDBName.Text,FDBPath,teDBName.Text,teDBName.Text,FDBPath,teDBName.Text]));
            ExecSQL;

    这里两个SIZE分别是数据库文件和日志文件的初始大小,单位MB。Chinese_PRC_CI_AS为默认排序规则

    需要注意的是,如果库正在被使用,DROP会出错。貌似用SQLDMO可以杀掉连那个库的进程,可以用这个野蛮残忍的办法停止对库的使用。。。

    修改SQL,创建数据库结构

    以下需要在刚创建的数据库中执行

    1.去掉注释(--和/* */)

            Mark:=False;
            for Index:=0 to SQLList.Count-1 do
            begin
              //--开头
              TmpStr:=Trim(SQLList[Index]);
              if Copy(TmpStr,1,2)='--' then
                SQLList[Index]:=''
              else begin
                if Mark then
                begin
                  if Copy(TmpStr,Length(TmpStr)-1,2)='*/' then
                  begin
                    Mark:=False;
                  end;
                  SQLList[Index]:='';
                end
                else begin
                  if Copy(TmpStr,1,2)='/*' then
                  begin
                    Mark:=True;
                    SQLList[Index]:='';
                  end;
                end;
              end;
            end;

    2.去掉go

           SQLList.Text:=StringReplace(SQLList.Text,#13#10'GO'#13#10,#13#10,[rfReplaceAll,rfIgnoreCase]);

    3.在CREATE VIEW前加exec

           SQLList.Text:=StringReplace(SQLList.Text,'CREATE VIEW ','exec(''CREATE VIEW ',[rfReplaceAll,rfIgnoreCase]);
            Mark:=False;
            for Index:=0 to SQLList.Count-1 do
            begin
              if Mark then
              begin
                //把exec('')之中的'替换为'',否则报错
                SQLList[Index]:=StringReplace(SQLList[Index],'''','''''',[rfReplaceAll,rfIgnoreCase]);
                if System.Pos('SET ',SQLList[Index])>0 then
                begin
                  Mark:=False;
                  //CREATE VIEW结尾加')
                  SQLList[Index-1]:=SQLList[Index-1]+''')';
                end;
              end
              else if System.Pos('exec(''CREATE VIEW ',SQLList[Index])>0 then
              begin
                Mark:=True;
              end;
            end;

    4.存储过程前加exec

    这里注意存储过程中经常出现SET,所以不能让SET做为判断'CREATE PROCEDURE 结束的标志,而要用

    SET QUOTED_IDENTIFIER OFF,只要是企业管理器导出的创建存储过程语句,必定以SET QUOTED_IDENTIFIER OFF紧跟着创建语句

            SQLList.Text:=StringReplace(SQLList.Text,'CREATE PROCEDURE ','exec(''CREATE PROCEDURE ',[rfReplaceAll,rfIgnoreCase]);
            Mark:=False;
            for Index:=0 to SQLList.Count-1 do
            begin
              if Mark then
              begin
                //把exec('')之中的'替换为'',否则报错
                SQLList[Index]:=StringReplace(SQLList[Index],'''','''''',[rfReplaceAll,rfIgnoreCase]);
                if System.Pos('SET QUOTED_IDENTIFIER OFF',SQLList[Index])>0 then
                begin
                  Mark:=False;
                  //CREATE PROCEDURE 结尾加')
                  SQLList[Index-1]:=SQLList[Index-1]+''')';
                end;
              end
              else if System.Pos('exec(''CREATE PROCEDURE ',SQLList[Index])>0 then
              begin
                Mark:=True;
              end;
            end;

    最后

    SQL.Assign(SQLList),可以执行Query了

    不过我觉得SQLDMO应该有直接执行SQL语句的功能,就是支持GO和注释等的Transact-SQL,时间关系,没去深入研究SQLDMO,我暂时只是把这玩艺拿来刷数据库列表用

  • 相关阅读:
    正则表达式中匹配中文
    计算机中的颜色——颜色概述
    人物系列Claude Shannon
    reading listfrom other blog
    how to write Makefile
    《麻省理工大学开放课程:线性代数》[中英双语字幕]视频下载
    正则表达式30分钟入门教程
    usage of fscanf and other read functions in C/C++
    《麻省理工大学开放课程:线性代数》学习
    Open review of papers
  • 原文地址:https://www.cnblogs.com/jiangyuxuan/p/1348865.html
Copyright © 2011-2022 走看看