h2 VIEW正确的SELECT语句有问题

时间:2015-01-04 03:17:16

标签: sql h2

我正在研究一个由h2数据库支持的会计系统。我有很多观点来汇总ACCOUNTSTRANSACTIONSTEMPLATE_TRANSACTIONS表中的数据。

问题,简而言之

虽然我有SELECT语句可以准确生成我需要在VIEW_TEMPLATES_DATA视图中看到的数据,但当我在SELECT内使用CREATE VIEW VIEW_TEMPLATES_DATA然后转到{时{1}},h2告诉我其中的一个列无法找到。 h2如何对'裸'SELECT * FROM VIEW_TEMPLATES_DATA语句完全满意,但一旦将其打包成SELECT语句就不高兴了?

我为这篇文章的篇幅道歉,但CREATE VIEW陈述必然相当漫长而复杂,并且有必要的背景信息。该帖子包含构建小型测试数据库所需的所有SQL,供感兴趣的人使用。

背景

模板事务是一种以“原型”形式存储常用事务的方法:模板事务的唯一要求是它具有旁白。日期,金额,账户等都是可选的。

帐户可能与模板交易相关联,可以在帐户核对时自动实例化。例如,这对于信用卡帐户非常方便。

当然,模板事务的'leg'存储在与存储头信息的表中不同的表中。

所以,我们有以下表格和视图(当然,从真实的东西中简化):

SELECT

以下是上述代码:

ACCOUNTS
ID   NAME         PAYER_TEMPLATE_ID   CURRENCY_ID
-------------------------------------------------
95   account0     null                1
122  account1     47                  0
178  foo bar      35                  0

TEMPLATE_TRANSACTIONS
ID   NARRATION
--------------
32   template0
35   template1
47   template2

TEMPLATE_TRANSACTION_LEGS
ID   HEAD_TABLE_ID   ACCOUNT_ID   AMOUNT
----------------------------------------
23   32              95           null
74   35              178          500
75   35              null         -500

VIEW_TEMPLATES_DATA
HEAD_ID   NARRATION   LEG_ID   ACCOUNT_ID   AMOUNT   CURRENCY_ID
----------------------------------------------------------------
23        template0   23       95           null     1
35        template1   74       178          500      0
35        template1   75       null         -500     null
47        template2   null     null         null     null

一段时间以来,这在生产数据库中运行良好。现在我需要在视图中添加一个布尔列CREATE TABLE TEMPLATE_TRANSACTIONS( ID BIGINT NOT NULL PRIMARY KEY, NARRATION VARCHAR NOT NULL DEFAULT ' ' ); CREATE TABLE CURRENCIES( ID BIGINT NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR DEFAULT '' ); CREATE TABLE ACCOUNTS( ID BIGINT NOT NULL PRIMARY KEY, NAME VARCHAR DEFAULT '', PAYER_TEMPLATE_ID BIGINT, CURRENCY_ID BIGINT NOT NULL ); ALTER TABLE ACCOUNTS ADD CONSTRAINT ACCOUNTS_FK_2 FOREIGN KEY(CURRENCY_ID) REFERENCES CURRENCIES(ID); ALTER TABLE ACCOUNTS ADD CONSTRAINT ACCOUNTS_FK_3 FOREIGN KEY(PAYER_TEMPLATE_ID) REFERENCES TEMPLATE_TRANSACTIONS(ID); CREATE TABLE TEMPLATE_TRANSACTION_LEGS( ID BIGINT NOT NULL PRIMARY KEY, HEAD_TABLE_ID BIGINT NOT NULL, ACCOUNT_ID BIGINT DEFAULT NULL, AMOUNT INT DEFAULT NULL ); ALTER TABLE TEMPLATE_TRANSACTION_LEGS ADD CONSTRAINT TEMPLATE_TRANSACTION_LEGS_FK_1 FOREIGN KEY(HEAD_TABLE_ID) REFERENCES TEMPLATE_TRANSACTIONS(ID); ALTER TABLE TEMPLATE_TRANSACTION_LEGS ADD CONSTRAINT TEMPLATE_TRANSACTION_LEGS_FK_2 FOREIGN KEY(ACCOUNT_ID) REFERENCES ACCOUNTS(ID); CREATE VIEW VIEW_TEMPLATES_DATA AS (SELECT TEMPLATE_TRANSACTIONS.ID AS HEAD_ID, TEMPLATE_TRANSACTIONS.NARRATION, TEMPLATE_TRANSACTION_LEGS.ID AS LEG_ID, TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID, TEMPLATE_TRANSACTION_LEGS.AMOUNT, ACCOUNTS.CURRENCY_ID FROM (TEMPLATE_TRANSACTIONS LEFT OUTER JOIN TEMPLATE_TRANSACTION_LEGS ON TEMPLATE_TRANSACTION_LEGS.HEAD_TABLE_ID = TEMPLATE_TRANSACTIONS.ID) LEFT OUTER JOIN ACCOUNTS ON TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID = ACCOUNTS.ID ); INSERT INTO CURRENCIES (ID, DESCRIPTION) VALUES (0, 'currency0'); INSERT INTO CURRENCIES (ID, DESCRIPTION) VALUES (1, 'currency1'); INSERT INTO TEMPLATE_TRANSACTIONS (ID, NARRATION) VALUES (32, 'template0'); INSERT INTO TEMPLATE_TRANSACTIONS (ID, NARRATION) VALUES (35, 'template1'); INSERT INTO TEMPLATE_TRANSACTIONS (ID, NARRATION) VALUES (47, 'template2'); INSERT INTO ACCOUNTS (ID, NAME, PAYER_TEMPLATE_ID, CURRENCY_ID) VALUES (95, 'account0', null, 1); INSERT INTO ACCOUNTS (ID, NAME, PAYER_TEMPLATE_ID, CURRENCY_ID) VALUES (122, 'account1', 47, 0); INSERT INTO ACCOUNTS (ID, NAME, PAYER_TEMPLATE_ID, CURRENCY_ID) VALUES (178, 'foo bar', 35, 0); INSERT INTO TEMPLATE_TRANSACTION_LEGS (ID, HEAD_TABLE_ID, ACCOUNT_ID, AMOUNT) VALUES (23, 32, 95, null); INSERT INTO TEMPLATE_TRANSACTION_LEGS (ID, HEAD_TABLE_ID, ACCOUNT_ID, AMOUNT) VALUES (74, 35, 178, 500); INSERT INTO TEMPLATE_TRANSACTION_LEGS (ID, HEAD_TABLE_ID, ACCOUNT_ID, AMOUNT) VALUES (75, 35, null, -500); ,对于ID为IS_PAYER的任何模板事务,它将为TRUE。如上所述,我有ACCOUNTS.PAYER_TEMPLATE_ID语句,它完全符合我的要求:

SELECT

但是当我这样做时:

HEAD_ID   NARRATION   LEG_ID   ACCOUNT_ID   AMOUNT   CURRENCY_ID   IS_PAYER
---------------------------------------------------------------------------
32        template0   23       95           null     1             FALSE
35        template1   74       178          500      0             TRUE
35        template1   75       null         -500     null          TRUE
47        template2   null     null         null     null          TRUE

SELECT TEMPLATE_TRANSACTIONS.ID     AS HEAD_ID,
   TEMPLATE_TRANSACTIONS.NARRATION,
   TEMPLATE_TRANSACTION_LEGS.ID     AS LEG_ID,
   TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID,
   TEMPLATE_TRANSACTION_LEGS.AMOUNT,
   ACCOUNTS.CURRENCY_ID,
   IS_PAYER
FROM (
   (TEMPLATE_TRANSACTIONS LEFT OUTER JOIN TEMPLATE_TRANSACTION_LEGS ON TEMPLATE_TRANSACTION_LEGS.HEAD_TABLE_ID = TEMPLATE_TRANSACTIONS.ID)
    LEFT OUTER JOIN ACCOUNTS ON TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID = ACCOUNTS.ID)
JOIN
   (SELECT TEMPLATE_ID, (CASE WHEN PAYER_TEMPLATE_ID IS NOT NULL THEN TRUE ELSE FALSE END) AS IS_PAYER FROM 
      (SELECT TEMPLATE_TRANSACTIONS.ID AS TEMPLATE_ID, ACCOUNTS.PAYER_TEMPLATE_ID AS PAYER_TEMPLATE_ID FROM 
          ACCOUNTS RIGHT JOIN TEMPLATE_TRANSACTIONS ON ACCOUNTS.PAYER_TEMPLATE_ID =TEMPLATE_TRANSACTIONS.ID))
ON TEMPLATE_ID = TEMPLATE_TRANSACTIONS.ID

然后转到DROP VIEW VIEW_TEMPLATES_DATA; CREATE VIEW VIEW_TEMPLATES_DATA AS (SELECT TEMPLATE_TRANSACTIONS.ID AS HEAD_ID, TEMPLATE_TRANSACTIONS.NARRATION, TEMPLATE_TRANSACTION_LEGS.ID AS LEG_ID, TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID, TEMPLATE_TRANSACTION_LEGS.AMOUNT, ACCOUNTS.CURRENCY_ID, IS_PAYER FROM ( (TEMPLATE_TRANSACTIONS LEFT OUTER JOIN TEMPLATE_TRANSACTION_LEGS ON TEMPLATE_TRANSACTION_LEGS.HEAD_TABLE_ID = TEMPLATE_TRANSACTIONS.ID) LEFT OUTER JOIN ACCOUNTS ON TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID = ACCOUNTS.ID) JOIN (SELECT TEMPLATE_ID, (CASE WHEN PAYER_TEMPLATE_ID IS NOT NULL THEN TRUE ELSE FALSE END) AS IS_PAYER FROM (SELECT TEMPLATE_TRANSACTIONS.ID AS TEMPLATE_ID, ACCOUNTS.PAYER_TEMPLATE_ID AS PAYER_TEMPLATE_ID FROM ACCOUNTS RIGHT JOIN TEMPLATE_TRANSACTIONS ON ACCOUNTS.PAYER_TEMPLATE_ID =TEMPLATE_TRANSACTIONS.ID)) ON TEMPLATE_ID = TEMPLATE_TRANSACTIONS.ID ); 它会告诉我SELECT * FROM VIEW_TEMPLATES_DATA

我真的不明白为什么我原来的观点是可以接受的,我的新TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID not found也是,但我的新SELECT不是!我在SQL中没有做太多,而且错误信息并不是很有用,我真的不知道该去哪里。

任何人都能指出我的解决方案吗?

1 个答案:

答案 0 :(得分:5)

问题是您在JOIN子句中使用的括号。删除后,视图上的SELECT将立即生效:

CREATE VIEW VIEW_TEMPLATES_DATA AS (SELECT
   TEMPLATE_TRANSACTIONS.ID     AS HEAD_ID,
   TEMPLATE_TRANSACTIONS.NARRATION,
   TEMPLATE_TRANSACTION_LEGS.ID     AS LEG_ID,
   TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID,
   TEMPLATE_TRANSACTION_LEGS.AMOUNT,
   ACCOUNTS.CURRENCY_ID,
   IS_PAYER
FROM  TEMPLATE_TRANSACTIONS
      LEFT OUTER JOIN TEMPLATE_TRANSACTION_LEGS ON TEMPLATE_TRANSACTION_LEGS.HEAD_TABLE_ID = TEMPLATE_TRANSACTIONS.ID
      LEFT OUTER JOIN ACCOUNTS ON TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID = ACCOUNTS.ID
      JOIN (SELECT TEMPLATE_ID, (CASE WHEN PAYER_TEMPLATE_ID IS NOT NULL THEN TRUE ELSE FALSE END) AS IS_PAYER
              FROM (SELECT TEMPLATE_TRANSACTIONS.ID AS TEMPLATE_ID, ACCOUNTS.PAYER_TEMPLATE_ID AS PAYER_TEMPLATE_ID
                      FROM ACCOUNTS
                           RIGHT JOIN TEMPLATE_TRANSACTIONS ON ACCOUNTS.PAYER_TEMPLATE_ID =TEMPLATE_TRANSACTIONS.ID))
      ON TEMPLATE_ID = TEMPLATE_TRANSACTIONS.ID
);

当您将第一个LEFT OUTER JOIN放在括号中时,第二个TEMPLATE_TRANSACTION_LEGS无法看到已加入的表格LEFT OUTER JOIN