65.9K
CodeProject 正在变化。 阅读更多。
Home

Postgres 中的 DBCreate

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (3投票s)

2008 年 12 月 22 日

CPOL

2分钟阅读

viewsIcon

26456

downloadIcon

447

一篇关于使用 PostgreSQL 创建数据库的文章。

DBCreate

引言

在安装数据库应用程序时,许多客户希望看到针对数据库执行的 SQL 代码。 他们中的大部分需要查看此代码以确保安全,有时还需要符合萨班斯-奥克斯利法规。 我想知道是否可以达到一个状态,即同时拥有 .SQL 文件以及一个用于在数据库上执行代码的程序。 过去,我们只是启动一个 shell,并向系统管理员显示结果。 我们还会检查输出文件中的“error”(错误)等词语。 虽然这可行,但这不是最优雅的方法。

Using the Code

该程序有一个主屏幕和两个面板,面板的启用与输入有关。 第一个面板收集执行一系列 SQL 所需的信息。 按钮用于 后退下一步 序列,但按钮名称也会在最后一步更改为 开始。 第二个屏幕显示一个文本框,该文本框将在从输入文件读取每个 SQL 语句后进行更新。 诀窍是将您想要的所有控件放入其各自的面板中。 这样,当您启用并显示所需的面板时,只需对面板进行操作,而无需对面板内的每个控件进行操作。

        /// 
        /// initialize the variables and screens. 
        /// 
        public DBIns()
        {
            InitializeComponent();
            panel2.Enabled = false;
            panel2.Visible = false;
            btnBack.Enabled = false;
        }

当按下按钮时,代码必须检查其当前状态,并更改需要更改的任何按钮名称,同时使面板可见并启用。 由于我实际上计划使用这段代码,因此我还添加了 errorprovider 来检查有效输入,然后再进入第二个面板。

        /// 
        /// click the back button. determine what to do. 
        /// 
        private void btnBack_Click(object sender, EventArgs e)
        {
            if (panel1.Enabled != true)
            {
                panel2.Enabled = false;
                panel2.Visible = false;
                panel1.Enabled = true;
                panel1.Visible = true;
                btnNext.Text = "Next ->";   // change the button to read next. 
                btnBack.Enabled = false;
            }
        }
        /// 
        /// click the next button. determine what to do. 
        /// 
        private void btnNext_Click(object sender, EventArgs e)
        {
            errorProvider1.Clear();
            // if panel 1 is enabled and a next button was pressed we
            // want to display panel2 and allow the user to press the start button. 
            if (panel1.Enabled == true)
            {
                // Check to see if the data was entered before we proceeed. 
                if (txtServer.Text.Length == 0)
                {
                    errorProvider1.SetError(txtServer,
                        "Please enter a valid server name");
                    return;
                }
                // Check to see if the data was entered before we proceeed. 
                if (txtDBName.Text.Length == 0)
                {
                    errorProvider1.SetError(txtDBName,
                        "Please enter a valid database name");
                    return;
                }
                // Check to see if the data was entered before we proceeed. 
                if (txtUser.Text.Length == 0)
                {
                    errorProvider1.SetError(txtUser, "Please enter a valid User name");
                    return;
                }
                // Check to see if the data was entered before we proceeed. 
                if (txtPassword.Text.Length == 0)
                {
                    errorProvider1.SetError(txtPassword,
                        "Please enter a valid password");
                    return;
                }
                panel1.Enabled = false;
                panel1.Visible = false;
                panel2.Enabled = true;
                panel2.Visible = true;
            
                
                btnNext.Text = "Start";
                btnBack.Enabled = true;
                panel2.Visible = true;
                textBox1.TabIndex = 1;
                textBox1.Focus();
                btnBack.TabIndex = 2;
                btnNext.TabIndex = 3;
            }
            else
            {
                NpgsqlRtns cl1;
                bool    bCreateDB;
                string strDBName;
                string strServer;
                string strUser;
                string strPassword;

                btnBack.Enabled = false;
                btnNext.Enabled = false;
                cl1 = new NpgsqlRtns();
                bCreateDB = chkBoxCreateDB.Checked;
                strDBName = txtDBName.Text;
                strServer = txtServer.Text;
                strUser = txtUser.Text;
                strPassword = txtPassword.Text;
                Subscribe(cl1);
                cl1.StartConv(bCreateDB, strDBName, strServer, strUser, strPassword);
            }
        }

startconv 过程处理数据库的创建(如果选中)以及解析文件中的 SQL 命令。

        public int StartConv(bool bCreateDB, string strDBName, string strServer,
            string strUser, string strPassword)
        {
            int ians = 0;

            ians = doConv(bCreateDB, strDBName, strServer, strUser, strPassword);
            return (ians);
        }
        /// 
        /// This routine does the actual database conversion process. 
        /// 
        private int doConv(bool bCreateDB, string strDBName, string strServer,
            string strUser, string strPassword)
        {
            int     ians = 0;
            string  strlastCommand;
            string  strCommand;
            FileRtns    frtn;
            NpgsqlConnection conn;
            //
            // first use the SA account to create a datbase if requested.  
            //
            strCommand = string.Format(
                "Server={0};Port=5432;User Id={1};Password={2};Database=postgres;",
                strServer, strUser, strPassword);
            conn = new NpgsqlConnection(strCommand);
            conn.Open();
            // if we were requested toc reate the datbase then do so 
            if (bCreateDB)
            {
                strCommand = string.Format(
                  "CREATE DATABASE \"{0}\" WITH OWNER = postgres ENCODING = 'WIN1252';",
                  strDBName);
                strlastCommand = strCommand;
                NpgsqlCommand command = new NpgsqlCommand(strCommand, conn);
                try
                {
                    command.ExecuteScalar();
                    strResult = "Create Database - Successful";
                }
                catch
                {
                    strResult = "Error ";
                }
                if (Tick != null)
                {
                    Tick(this, e);
                }
            }
            conn.Close();

            //
            // Now log into the requested database and issue the sql statements. 
            //

            // create a file routines class to read the sql statements form the file. 
            frtn = new FileRtns();
            frtn.FileOpen();
            strCommand = string.Format(
                "Server={1};Port=5432;User Id={2};Password={3};Database={0};",
                strDBName, strServer, strUser, strPassword);
            conn = new NpgsqlConnection(strCommand);
            conn.Open();
            // while there are statements in the file read them. 
            while (true)
            {
                strCommand = frtn.FileRead();
                if (strCommand.Length == 0)
                {
                    break;  // we are at the end of the file. 
                }
                strlastCommand = strCommand;
                NpgsqlCommand command = new NpgsqlCommand(strCommand, conn);
                // execute the sql statement. 
                try
                {
                    command.ExecuteScalar();
                    strResult = findCommand(strCommand) + " - Successful";
                }
                catch
                {
                    strResult = findCommand(strCommand) + " - Error";
                }
                if (Tick != null)
                {
                    Tick(this, e);
                }
            }
            conn.Close();
            frtn.FileClose();

            strResult = "Finished";
            if (Tick != null)
            {
                Tick(this, e);
            }

            return (ians);
        }

在本版本中,文件解析器会读取直到第一个分号。 我知道这仅适用于单行命令(这有很多),但对于函数而言会失败。 在下一个版本中,我将更新此功能以包含函数。 为了使这项工作更容易,我已经封装了该类。

        /// 
        /// Read the frist line from the file.
        /// We will read until the first semicolon since that ends the sql statement. 
        /// 
        public string FileRead()
        {
            string  strResult = "";
            string  strBuffer = "";

            while ((sr.EndOfStream)!= true) {
                strBuffer = sr.ReadLine();
                strBuffer = strBuffer.Trim();
                if (strBuffer.EndsWith(";"))
                {
                    strResult += strBuffer;
                    break;
                }
                strResult += strBuffer;
            }
            return (strResult);
        }

执行命令后,会对其进行解析以进行显示,并发送一个事件。 主程序捕获该事件,然后在文本框中向用户显示该命令。

虽然有其他程序专注于数据库创建,但由于 SQL 文件可以独立使用,也可以作为此程序的一部分使用,因此该程序具有一定的独特性。 如果您想下载 PostgreSQL,请访问 此处

其他注意事项

下一个版本将包括对函数的修复,以及对 PostgreSQL 的其他一些改进。

历史

12 月 19 日 - 第一个版本

© . All rights reserved.