2015-12-05 44 views
1

現在我正在編寫一個具有PostgreSQL數據庫的應用程序。 我的任務是編寫根據new.id執行SQL語句的觸發器。基於NEW.id的動態SUM基於觸發函數

只有一個問題,即觸發器不執行查詢。它只是插入任何東西。

DB output

CREATE OR REPLACE FUNCTION bill_creator() 
RETURNS TRIGGER AS $build_bill$ 
declare 
    summ INTEGER; 
BEGIN 
    SELECT SUM(ITEMS.PRICE) INTO summ 
    FROM ITEMS 
    INNER JOIN PARTS 
    ON PARTS.ITEM_ID = ITEMS.ID AND PARTS.ORDER_ID = NEW.ID; 

    INSERT INTO BILLS (
     created, 
     summary, 
     cashier_id, 
     customer_id, 
     order_id, 
     created_at, 
     updated_at, 
     options 
    ) 
    VALUES (
     current_date, 
     summ, 
     1, 
     new.customer_id, 
     new_id, 
     current_timestamp, 
     current_timestamp, 
     'None' 
    ); 
    RETURN NEW; 
END; 
$build_bill$ LANGUAGE plpgsql; 

CREATE OR REPLACE TRIGGER build_bill AFTER INSERT ON ORDERS 
FOR EACH ROW EXECUTE PROCEDURE bill_creator(); 

我使用Rails,所以表格由ActiveRecords創建的,但它們存儲在架構。

create_table "bills", force: :cascade do |t| 
    t.datetime "created" 
    t.string "options" 
    t.integer "summary" 
    t.integer "cashier_id" 
    t.integer "customer_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.integer "order_id" 
end 

create_table "orders", force: :cascade do |t| 
    t.integer "customer_id" 
    t.integer "waiter_id" 
    t.integer "manager_id" 
    t.integer "chef_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

create_table "parts", force: :cascade do |t| 
    t.integer "order_id" 
    t.integer "item_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

create_table "items", force: :cascade do |t| 
    t.integer "price" 
    t.string "description" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.integer "menu_id" 
end 

add_index "parts", ["item_id"], name: "index_parts_on_item_id", using: :btree 
add_index "parts", ["order_id"], name: "index_parts_on_order_id", using: :btree 
+0

嘗試設置數據庫作用域 – MHSFisher

+0

請爲所涉及的所有表顯示「create trigger」語句和「create table」。 –

+0

請用文本格式替換您的實際「數據庫輸出」鏈接。外部鏈接對此沒有好處。 –

回答

1

你的功能看起來基本不錯。我簡化並修正了一些問題:

CREATE OR REPLACE FUNCTION bill_creator() 
    RETURNS TRIGGER AS 
$build_bill$ 
BEGIN 
    INSERT INTO bills (
    created, 
    summary, 
    cashier_id, 
    customer_id, 
    order_id, 
    created_at, 
    updated_at, 
    options 
    ) 
    SELECT 
    current_date, 
    SUM(i.price) 
    1, 
    NEW.customer_id, 
    NEW.id    -- ! 'new_id was undefined ! 
    current_timestamp, 
    current_timestamp, 
    'None' 
    FROM parts p 
    JOIN items i ON p.item_id = i.id 
    WHERE p.order_id = NEW.id; 

    RETURN NULL; 
END 
$build_bill$ LANGUAGE plpgsql; 

您不需要單獨的SELECT和變量賦值。將它集成到一個INSERT中,速度更快。結果是一樣的,即使沒有找到任何東西,聚合函數sum()總是返回一行。

new_id未定義,我假定你的意思是NEW.id

我用RETURN NULL因爲,per documentation:

行級觸發器的返回值解僱AFTER [...]總是被忽略;它可能是空的。

不確定爲什麼你有createdcreated_at。兩者都是類型定義的AS t.datetime,應翻譯成Postgres timestamp。也不知道爲什麼你寫第current_date而不是current_timestamp

但是,插入的summary爲NULL並不奇怪。在orders中插入一行後立即在parts中不存在相關條目,但是 - 假設參照完整性。所以在這一點上插入一個總和bill的想法是必然會失敗。您必須在UPDATE列中插入/更新/刪除每個新的part。這是跳蚤的袋子,你必須處理,以保持該總電流 - 或多或少...

我建議你放置列bill.summary完全,並使用VIEW而不是動態計算的總和。可以是MATERIALIZED VIEW以避免重複聚合。