【问题标题】:Creating non-existent database tables in code在代码中创建不存在的数据库表
【发布时间】:2010-07-06 10:23:27
【问题描述】:

到目前为止,我的公司一直厌恶数据库,并坚持将所有数据存储在逗号分隔的文件中。我遇到了一个独特的客户应用程序,我相信它会从使用关系数据库中受益。该应用程序要求存储有关制造过程的“摘要”数据和多个子过程的“详细”数据。子流程需要链接到流程摘要。

我的问题:在写入该表之前检查表是否存在是否正常/合适,如果该表不存在则创建它?既然我正在输入这个,这可能会导致一个更大的问题;如果数据库不存在,我应该创建数据库和它需要的任何表吗?

【问题讨论】:

  • '我的公司厌恶数据库,坚持将所有数据存储在逗号分隔的文件中'OMG,太可怕了。
  • 在某些情况下,我认为这很恐怖。我们拥有轻松快速地读取/写入平面文件的所有好处,但无法处理关系数据,因为没有人费心开发它。

标签: .net sql sqlite vb6


【解决方案1】:

使用 SQLite,自己创建表是一种好方法。您不需要为您的客户制定比现在更复杂的安装说明,如果数据库完全在您的应用程序内部,他们可能甚至不关心它的格式,只要您的软件可靠且快速。

例如,如今 Firefox 使用 SQLite 作为其内部存储,它们从不打扰用户创建数据库。用户喜欢这样。 :)

但我不会太担心在引用表之前立即创建数据库:相反,我会将创建逻辑放在应用程序启动或安装时,以更合适的为准。现在在您的应用程序中创建的 CSV 文件在哪里?每次引用它们时,它们是否都是重新创建的?还是它们也是在初始化或安装例程中创建的?

【讨论】:

  • CSV 文件分散在一个嵌套的目录结构中,并在应用程序启动时创建。在这个应用程序中,在启动时创建非常有意义。
【解决方案2】:

不,在代码中创建表是不正常的。如果您需要关系数据库,则需要在使用前对其进行设计。关系数据库不容小觑。

如果您以前从未这样做过,这里有一个主题介绍...http://www.databasedev.co.uk/design_basics.html

(对不起,如果你知道这一切;我不是故意光顾的。)

【讨论】:

  • 使用前设计好数据库是正常的。但是对于桌面应用程序,使用基于文件的数据库,通过代码创建数据库可能是合适的。在许多应用程序共享一个服务器数据库的企业环境中,情况就不同了。
  • 你是说安装的时候吗?我以为 Ryan 的意思是在应用程序运行时;这真的很正常吗?我的意思是,除了数据库定义工具。还是我在这里抓住了错误的一端?
  • 这不是真的。商业应用程序在某些情况下会创建表甚至整个数据库。针对各种客户提供的数据库服务器运行的应用程序通常会在安装过程中创建整个数据库。在新版本中发布的应用程序通常会在每个版本中升级其数据库(包括添加表)。
【解决方案3】:

通常我会说不存在表意味着某处存在问题。动态创建的表通常是出现问题的迹象,如果它们是标准表(例如 tblUsers),那么它们应该始终存在并作为设置过程的一部分进行设置。

当您在代码开发方面有了一定的距离并升级数据库以添加额外的表但希望您的代码与新设计和旧设计一起使用时,我认为检查存在性是有意义的。在这种情况下,在尝试使用表之前检查表是否存在是有意义的。

一般来说,虽然您应该知道数据库中有哪些表,因此不需要检查它们是否存在。而且我完全不知道为什么您要尝试访问不存在的数据库...您是否正在考虑某种惰性设置过程,其中可以即时添加新客户端(或类似客户端)及其创建的数据库?如果是这样,我将有一个流程来创建和设置这些新数据库。

【讨论】:

    【解决方案4】:

    对于这种类型的上下文,Sqlite 具有“如果不存在则创建表”语法。 (检查http://www.sqlite.org/lang_createtable.html)大多数库还可以选择在连接时创建一个新的sqlite数据库文件,如果它不存在的话。

    【讨论】:

      【解决方案5】:

      SubSonic SimpleRepository 一般可以很好地处理这种情况(外键关系除外)。

      通常我不会通过代码创建和维护数据库和/或表,因为这很容易在你的脸上炸毁。

      【讨论】:

        【解决方案6】:

        在编写应用程序之前,您应该知道数据的结构。

        尽可能将数据和应用程序分开。

        使用数据访问层还意味着,如果您已经拥有一个 Windows 应用程序(例如),然后想要创建一个 Web 前端,您可以轻松地重用 DAL。

        如果数据访问嵌入在应用程序中,则重用该代码会更加困难。

        【讨论】:

        • ...此外,如果数据库模式创建嵌入在应用程序中...不寒而栗!
        【解决方案7】:

        关系数据库允许轻松共享数据。

        您可以在不需要共享数据时使用文件。

        DataSet 序列化是存储文件信息的好选择。您维护的数据结构类似于关系数据库。

        Xml 序列化很慢,但您可以使用 BinaryFormatter:

        RemotingFormat = SerializationFormat.Binary
        

        此选项使二进制序列化快速而紧凑。

        Code-Project 包含一篇“快速序列化”文章。但这不是标准的。

        【讨论】:

          【解决方案8】:

          答案取决于您的项目的性质。

          如果这是一个具有单个实例的内部系统,则可以合理地节省一些开发时间,并在更新软件时使用新表手动更新数据库。在这种情况下,您不必担心让您的软件添加表格。

          如果您将此软件提供给客户甚至组织内的远程站点,并且安装和升级是在“现场”进行的,那么您的软件的每个新版本都应该自行升级数据库是合理的。您不一定要在每个 SQL 命令之前执行此检查,也不一定要在每次运行软件时执行此检查。您可以在数据库中的某处存储“数据结构版本号”并在启动时检查该数字,仅在该数字低于当前版本时应用结构更新。

          【讨论】:

            【解决方案9】:

            许多 RDBMS 支持 DDL SQL 语句。 ADOX 也可以与某些数据库一起使用,以执行诸如创建新表之类的操作。我认为这根本不是特别奇特,尤其是当程序使用某种“嵌入式”基于文件的数据库作为内部数据存储甚至作为输出格式时。

            根据需要创建索引、约束、关系等没有问题。示例:

            Private Const WG_CONNSTRING As String = _
                  "Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Engine Type=5;" _
                & "Jet OLEDB:Create System Database=True;" _
                & "Data Source='$MDB$.mdw'"
            Private Const DB_CONNSTRING As String = _
                  "Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Engine Type=5;" _
                & "Jet OLEDB:System Database='$MDB$.mdw';" _
                & "Data Source='$MDB$.mdb'"
            
            'Exits with new MDB created, populated from initial data
            'in text files, and cnDB left open.
            
            Dim catDB As Object 'Don't early-bind ADOX objects.
            
            Set catDB = CreateObject("ADOX.Catalog")
            catDB.Create Replace$(WG_CONNSTRING, "$MDB$", MDB_NAME)
            catDB.Create Replace$(DB_CONNSTRING, "$MDB$", MDB_NAME)
            
            Set cnDB = catDB.ActiveConnection
            With cnDB
                .Execute "CREATE TABLE Fruits (" _
                       & "FruitID IDENTITY NOT NULL CONSTRAINT PK_FruitID PRIMARY KEY," _
                       & "Fruit TEXT(50) WITH COMPRESSION NOT NULL UNIQUE" _
                       & ")", _
                         , adCmdText
                .Execute "CREATE TABLE Pies (" _
                       & "PieID IDENTITY NOT NULL CONSTRAINT PK_PieID PRIMARY KEY," _
                       & "Pie TEXT(50) WITH COMPRESSION NOT NULL," _
                       & "FruitID INTEGER NOT NULL CONSTRAINT FK_FruitID " _
                       & "REFERENCES Fruits (FruitID)" _
                       & ")", _
                         , adCmdText
                .Execute "CREATE VIEW PiesView (ID, Pie, Fruit) AS " _
                       & "SELECT PieID AS ID, Pie, Fruit " _
                       & "FROM Pies LEFT OUTER JOIN Fruits " _
                       & "ON Pies.FruitID = Fruits.FruitID", _
                         , adCmdText
                .Execute "CREATE PROC InsertPie(NewPie TEXT(50), FruitName TEXT(50)) AS " _
                       & "INSERT INTO Pies (Pie, FruitId) " _
                       & "SELECT NewPie, Fruits.FruitId FROM Fruits " _
                       & "WHERE Fruit = FruitName", _
                         , adCmdText
            End With
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-06-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多