2011-08-18 4 views
6

एक ट्रिगर में मैं देखना चाहता हूं कि एसक्यूएल क्वेरी ने इस ट्रिगर को ट्रिगर किया था। मैंने current_query() पोस्टग्रेस्क्ल (8.4) का कार्य किया।

सब ठीक है, लेकिन अगर ट्रिगर तैयार कथन द्वारा निष्पादित किया जाता है तो मुझे सही मूल्यों के बजाय प्लेसहोल्डर्स ($ 1) मिलते हैं। उदाहरण के लिए (लॉग क्वेरी):

delete from some_table where id=$1 

क्या यह मान/पैरामीटर प्राप्त करने/प्राप्त करने का कोई तरीका है?

संपादित (उदाहरण के लिए जोड़ा):

--table for saving query 
create table log_table (
query text 
) 

--table for trigger 
create table some_table (
id text 
) 
--function itself 
CREATE FUNCTION save_query() RETURNS trigger AS $$ 
    switch $TG_op { 
    DELETE { 
      spi_exec "INSERT INTO log_table (query) VALUES (current_query())" 
     } 
    default { 
      return OK 
     } 
    } 
    return OK 
$$ LANGUAGE pltcl; 

एक ट्रिगर बनाने:

create trigger test_trigger before delete on some_table for each row execute procedure save_query(); 

तैयार बयान हाइबरनेट से क्रियान्वित किया जाता है।

संपादित फिर से (जावा हिस्सा जोड़ा)

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 

public class DeleteUsingPreparedStmt { 

    public static void main(String[] args) { 
     try { 
      String deleteString = "delete from floors where id = ? "; 
      final int idToDelte = 1; 

      Class.forName("org.postgresql.Driver"); 
      String url = "jdbc:postgresql://127.0.0.1:5432/YOUR_DATABASE"; 
      Connection conn = DriverManager.getConnection(url, "user", "password"); 

      PreparedStatement deleteStmt = conn.prepareStatement(deleteString); 
      deleteStmt.setInt(1, idToDelte); 
      deleteStmt.executeUpdate(); 
     } catch (Exception e) { 
      //hide me :) 
     } 
    } 
} 

आप एक JDBC ड्राइवर की जरूरत है - click

+0

आप अपने प्रश्न में इस के लिए उदाहरण कोड लिख सकते हैं? –

+2

संपादित प्रश्न। मैंने थोड़ा सा कोड सरल किया, लेकिन यह उसी तरह काम करता है। –

उत्तर

4

यहाँ कुछ काम कर कोड है (Debian उपयोगकर्ताओं के लिए: बस postgresql-pltcl-8.4 पैकेज स्थापित करने और चलाने CREATE LANGUAGE pltcl;)

CREATE TABLE log_table (
    id serial, 
    query text 
); 

CREATE TABLE floors (
    id serial, 
    value text 
); 

INSERT INTO floors(value) VALUES ('aaa'), ('bbb'); 

CREATE OR REPLACE FUNCTION save_query() RETURNS trigger AS $$ 
    switch $TG_op { 
     DELETE { 
      spi_exec "INSERT INTO log_table (query) VALUES (current_query())" 
     } 
     default { 
      return OK 
     } 
    } 
    return OK 
$$ LANGUAGE pltcl; 

CREATE TRIGGER test_trigger 
    BEFORE DELETE ON floors 
    FOR EACH ROW 
    EXECUTE PROCEDURE save_query(); 

हालांकि मैं तैयार बयान में प्लेसहोल्डर नहीं मिल सकता है (यह EXECUTE deleteFromFloors(2); रिटर्न):

TABLE log_table; 
id | query 
----+------- 
(0 rows) 
DELETE FROM floors WHERE id = 1; 
DELETE 1 
TABLE log_table; 
id |    query    
----+---------------------------------- 
    1 | DELETE FROM floors WHERE id = 1; 
(1 row) 
PREPARE deleteFromFloors(integer) AS 
    DELETE FROM floors WHERE id = $1; 
PREPARE 
EXECUTE deleteFromFloors(2); 
DELETE 1 
TABLE log_table; 
id |    query    
----+---------------------------------- 
    1 | DELETE FROM floors WHERE id = 1; 
    2 | EXECUTE deleteFromFloors(2); 
(2 rows) 

संपादित करें:

वर्कअराउंड उपयोग 01 के रूप मेंरिकॉर्ड (टीसीएल में सरणी के रूप में प्रतिनिधित्व), वहां से आईडी कॉलम लाएं और replace फ़ंक्शन का उपयोग $1 के बजाय करने के लिए करें। PL/pgSQL और पी एल/Tcl: यहाँ आप दो समाधान है

CREATE OR REPLACE FUNCTION save_query() RETURNS TRIGGER AS $$ 
BEGIN 
    INSERT INTO log_table (query) 
     VALUES (replace(current_query(), '$1', OLD.id::text)); 
    RETURN OLD; 
END; 
$$ LANGUAGE plpgsql; 

CREATE OR REPLACE FUNCTION save_query() RETURNS trigger AS $$ 
    switch $TG_op { 
     DELETE { 
      spi_exec "INSERT INTO log_table (query) 
       VALUES (replace(current_query(), '\$1', '$OLD(id)'))" 
     } 
     default { 
      return OK 
     } 
    } 
    return OK 
$$ LANGUAGE pltcl; 

परिणाम:

java -classpath '.:postgresql-8.4-702.jdbc4.jar' DeleteUsingPreparedStmt 

TABLE log_table; 
id |    query    
----+--------------------------------- 
    1 | delete from floors where id = 1 

(1 पंक्ति)

+0

आपने जो लिखा वह इस ट्रिगर का सही व्यवहार है। यह एक मौजूदा क्वेरी सहेजता है - इसलिए 'हटाएं हटाएं FromFloors (2)'। हालांकि जावा से, जो 'फर्श से हटाएं जहां id =?' एक अलग क्वेरी ($ 1 के साथ) सहेजा गया है। मुझे इसे दिखाने के लिए जावा में कोड का एक टुकड़ा लिखने दें। –

+0

एक जावा भाग जोड़ा गया। आप उत्तर दूसरों के लिए सहायक होंगे, लेकिन कम रैंकिंग के कारण मैं वोट नहीं दे सकता। –

+1

@ Michał: जोड़ा गया समाधान (उपलब्ध OLD रिकॉर्ड/सरणी से आईडी प्राप्त करना) –

संबंधित मुद्दे