Delphi:如何以编程方式创建Firebird数据库

3
我正在使用D2K9,Zeos 7Alpha和Firebird 2.1。
在添加自动增量字段之前,我已经将其工作。虽然我不确定我是否100%正确地做到了这一点。我不知道应该如何处理SQL代码、触发器、生成器等等的顺序。我尝试了几种组合,我猜我做错了什么,导致它无法正常工作。
当前演示: http://uploading.com/files/bd64d8m9/createdb.zip/ 当前错误:
It's getting an error here:

SQL Error:  Dynamic SQL Error SQL error code = -104 Token unknown - line 2, column 1 SET.
Error Code: -104. Invalid token The SQL:
 CREATE GENERATOR GEN_EMAIL_ACCOUNTS_ID;

请将生成器GEN_EMAIL_ACCOUNTS_ID设置为1;

来自IBExpert的SQL文件:

/******************************************************************************/
/*                 Generated by IBExpert 5/4/2010 3:59:48 PM                  */
/******************************************************************************/

/******************************************************************************/
/*        Following SET SQL DIALECT is just for the Database Comparer         */
/******************************************************************************/
SET SQL DIALECT 3;



/******************************************************************************/
/*                                   Tables                                   */
/******************************************************************************/


CREATE GENERATOR GEN_EMAIL_ACCOUNTS_ID;

CREATE TABLE EMAIL_ACCOUNTS (
    ID           INTEGER NOT NULL,
    FNAME        VARCHAR(35),
    LNAME        VARCHAR(35),
    ADDRESS      VARCHAR(100),
    CITY         VARCHAR(35),
    STATE        VARCHAR(35),
    ZIPCODE      VARCHAR(20),
    BDAY         DATE,
    PHONE        VARCHAR(20),
    UNAME        VARCHAR(255),
    PASS         VARCHAR(20),
    EMAIL        VARCHAR(255),
    CREATEDDATE  DATE,
    "ACTIVE"     BOOLEAN DEFAULT 0 NOT NULL /* BOOLEAN = SMALLINT CHECK (value is null or value in (0, 1)) */,
    BANNED       BOOLEAN DEFAULT 0 NOT NULL /* BOOLEAN = SMALLINT CHECK (value is null or value in (0, 1)) */,
    "PUBLIC"     BOOLEAN DEFAULT 0 NOT NULL /* BOOLEAN = SMALLINT CHECK (value is null or value in (0, 1)) */,
    NOTES        BLOB SUB_TYPE 0 SEGMENT SIZE 1024
);




/******************************************************************************/
/*                                Primary Keys                                */
/******************************************************************************/

ALTER TABLE EMAIL_ACCOUNTS ADD PRIMARY KEY (ID);


/******************************************************************************/
/*                                  Triggers                                  */
/******************************************************************************/


SET TERM ^ ;



/******************************************************************************/
/*                            Triggers for tables                             */
/******************************************************************************/



/* Trigger: EMAIL_ACCOUNTS_BI */
CREATE OR ALTER TRIGGER EMAIL_ACCOUNTS_BI FOR EMAIL_ACCOUNTS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF (NEW.ID IS NULL) THEN
    NEW.ID = GEN_ID(GEN_EMAIL_ACCOUNTS_ID,1);
END
^


SET TERM ; ^



/******************************************************************************/
/*                                 Privileges                                 */
/******************************************************************************/

触发器:

/******************************************************************************/
/*        Following SET SQL DIALECT is just for the Database Comparer         */
/******************************************************************************/
SET SQL DIALECT 3;

CREATE GENERATOR GEN_EMAIL_ACCOUNTS_ID;

SET TERM ^ ;



CREATE OR ALTER TRIGGER EMAIL_ACCOUNTS_BI FOR EMAIL_ACCOUNTS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF (NEW.ID IS NULL) THEN
    NEW.ID = GEN_ID(GEN_EMAIL_ACCOUNTS_ID,1);
END
^


SET TERM ; ^

生成器:

CREATE SEQUENCE GEN_EMAIL_ACCOUNTS_ID;
ALTER SEQUENCE GEN_EMAIL_ACCOUNTS_ID RESTART WITH 2;

/* Old syntax is:
CREATE GENERATOR GEN_EMAIL_ACCOUNTS_ID;
SET GENERATOR GEN_EMAIL_ACCOUNTS_ID TO 2;
*/

我的代码:请查看下面的评论演示。

3
如果您提供一大堆文字,可能会让人感到沮丧。请不要使用 codepre 标签,而是在编辑器中使用代码格式工具栏按钮,或者直接将代码缩进4个空格。此外,请删除所有不必要的内容,例如IBExpert脚本中的许多注释和空行,以便人们更好地理解问题。 - mghie
我没有代码格式化工具栏显示出来,但下次我会尝试更好地格式化所有内容,虽然在我的浏览器中它显示得很好。 - Brad
这里没有正常地显示(Mac OS X上的Firefox)。您应该拥有格式化按钮,它是编辑控件上面的工具栏中带有小“0”和“1”的按钮,带有“代码示例...”提示。 - mghie
这是我所拥有的演示 http://uploading.com/files/bd64d8m9/createdb.zip/。它会出现错误:SQL 错误:Dynamic SQL Error SQL error code = -104 Token unknown - line 2, column 1 SET。错误代码:-104。无效的标记 The SQL: CREATE GENERATOR GEN_EMAIL_ACCOUNTS_ID; SET GENERATOR GEN_EMAIL_ACCOUNTS_ID TO 1;需要 JVCL、Zeos db(使用版本 7)。 - Brad
1个回答

2
通常情况下,您可以以任何顺序创建Firebird数据库对象,前提是它们不相互依赖。如果它们相互依赖,那么显然您需要先创建被依赖的对象,然后再创建依赖的对象。
如果您有循环引用的对象,则首先创建一个空主体的对象,然后创建另一个对象,最后使用ALTER TABLE或相应的语句填充第一个对象的内容。像IBExpert、Database Workbench或FlameRobin这样的工具可以分析依赖关系,因此按照它们编写的脚本中的创建顺序总是有效的。
如果您的IBExpert创建的脚本有效,但是按照相同顺序执行操作的自己的代码无法正常工作,则可能原因在于IBExpert单独提交每个DDL语句(而您的代码没有)。您可以在自己的代码中执行相同的操作,并且应该这样做。您的自动增量列涉及触发器,触发器本身依赖于生成器,因此请确保在创建表和生成器之后,在创建触发器之前进行提交。
你应该确保只使用能够执行多个语句的数据库组件来执行多个语句。我不了解Zeos,但从this knowledge base article中可以看出,TZQueryTZUpdateSQL都支持在一次执行调用中执行多个语句。或者,你也可以使用TZSQLProcessor来加载由IBExpert创建的完整脚本并执行它。
另一方面,方法TZConnection.ExecuteDirect()可能不支持多个语句,在这种情况下,你将在第一个语句结束后遇到语法错误。
CREATE GENERATOR GEN_EMAIL_ACCOUNTS_ID;
SET GENERATOR GEN_EMAIL_ACCOUNTS_ID TO 2;

这里有两个语句,你可能需要分别将它们传递给 TZConnection.ExecuteDirect()

你能给我演示一下分别执行每个DDL的意思吗?我原本以为我在分别执行它们。 - Brad
@Brad:你需要分别处理它们,但你可能也需要提交你的工作。你可以设置一些Zeos选项来自动提交DDL,或者你需要显式地提交事务。我没有使用过Zeos,但是数据库对象或专用事务对象上应该有类似Commit()CommitRetaining()的方法。有关事务的更多信息,请参阅例如http://firebirdfaq.org上的文章。 - mghie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接