我正在研究一个由h2数据库支持的会计系统。我有很多观点来汇总ACCOUNTS
,TRANSACTIONS
和TEMPLATE_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中没有做太多,而且错误信息并不是很有用,我真的不知道该去哪里。
任何人都能指出我的解决方案吗?
答案 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
。