2015-01-04 9 views
5

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?

+0

Proszę publikować komunikaty o błędach. –

+0

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

Odpowiedz

3

Problem stanowią nawiasy używane w klauzulach JOIN. SELECT na widoku będzie działać jak najszybciej je usunąć:

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 
); 

Po umieszczeniu pierwszego LEFT OUTER JOIN między nawiasami, złączona tabela TEMPLATE_TRANSACTION_LEGS nie jest widoczny z drugiej LEFT OUTER JOIN.

+0

Perfect !! Dziękuję bardzo!! Zapamiętam to, nie mogłem zrozumieć, dlaczego nie było to widoczne, ponieważ wyraźnie tam jest, ale teraz widzę. Niezwykle jasne wyjaśnienie również, dzięki jeszcze raz. – skiaddict1

Powiązane problemy