Pracuję nad systemem księgowym, wspieranym przez bazę danych h2. Mam wiele widoków, aby zebrać dane z tabel ACCOUNTS
, i TEMPLATE_TRANSACTIONS
.h2 WIDOK ma problemy z prawidłową instrukcją SELECT
problem, w skrócie
Chociaż mam SELECT
oświadczenie, które produkuje dokładnie dane muszę zobaczyć w moim VIEW_TEMPLATES_DATA
widzenia, kiedy używam tego SELECT
wewnątrz CREATE VIEW VIEW_TEMPLATES_DATA
a następnie przejść SELECT * FROM VIEW_TEMPLATES_DATA
, h2 mówi mi, nie można znaleźć jednej z kolumn w tej kolumnie. W jaki sposób h2 może być całkowicie zadowolony z "nagiego" oświadczenia SELECT
, ale potem nie jest zadowolony, gdy zostanie zapakowany w instrukcję CREATE VIEW
?
Przepraszam za długość tego wpisu, ale oświadczenie SELECT
jest z konieczności dość długie i złożone, a także niezbędne informacje dodatkowe. Post zawiera wszystkie SQL potrzebne do zbudowania małej testowej bazy danych dla zainteresowanych.
Tło
Transakcja szablon jest sposób przechowywania często używanych transakcji w formie „prototype”: jedynym wymogiem dla transakcji szablonu jest to, że mają narrację. Data, kwoty, konta itp. Są opcjonalne.
Konto mogło powiązać z nim transakcję szablonu, która może być automatycznie utworzona, gdy konto zostanie uzgodnione. Jest to bardzo przydatne na przykład dla kont kart kredytowych.
Naturalnie, "nogi" dla transakcji szablonów przechowywane są w oddzielnej tabeli od tej, która przechowuje informacje w nagłówku.
Tak, mamy następujące tabele i widoki (oczywiście uproszczone od prawdziwych):
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
Oto kod do powyższego:
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);
To dobrze pracuje w produkcyjnej bazie danych przez jakiś czas. Teraz muszę dodać kolumnę boolowską, IS_PAYER
, do widoku, który będzie TRUE
dla wszystkich transakcji szablonów, których identyfikatory są w ACCOUNTS.PAYER_TEMPLATE_ID
. Jak wspomniano powyżej, mam SELECT
oświadczenie, które robi dokładnie to, co chcę:
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
ale kiedy to zrobić:
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
);
a następnie przejść SELECT * FROM VIEW_TEMPLATES_DATA
mówi mi TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID not found
.
Naprawdę nie rozumiem, dlaczego mój oryginalny widok był do przyjęcia, a mój nowy SELECT
też jest, ale mój nowy CREATE VIEW
nie jest! Nie robię dużo w SQL, a komunikat o błędzie nie jest dokładnie pomocny, a ja naprawdę nie wiem, dokąd się udać.
Czy każdy rodzaj ludzi może wskazać mi kierunek rozwiązania?
Proszę publikować komunikaty o błędach. –
Kiedy idę "SELECT * FROM VIEW_TEMPLATES_DATA" h2 mówi mi, że "Widok" PUBLIC.VIEW_TEMPLATES_DATA "jest nieprawidłowy:" Nie znaleziono kolumny "" TEMPLATE_TRANSACTION_LEGS.ACCOUNT_ID "" [42122-167] "; Instrukcja SQL: SELECT * FROM VIEW_TEMPLATES_DATA [90109-167] 90109/90109' – skiaddict1