PostgreSQL: फ़ंक्शन में तर्क के रूप में तालिका पास करें


11

मैं TYPEPostgreSQL में खोज रहा हूं । मेरे पास है TABLE TYPEकि कुछ टेबल को सम्मान (इंटरफ़ेस) देना चाहिए। उदाहरण के लिए:

CREATE TYPE dataset AS(
    ChannelId INTEGER
   ,GranulityIdIn INTEGER
   ,GranulityId INTEGER
   ,TimeValue TIMESTAMP
   ,FloatValue FLOAT
   ,Status BIGINT
   ,QualityCodeId INTEGER
   ,DataArray FLOAT[]
   ,DataCount BIGINT
   ,Performance FLOAT
   ,StepCount INTEGER
   ,TableRegClass regclass
   ,Tags TEXT[]
   ,WeightedMean FLOAT
   ,MeanData FLOAT
   ,StdData FLOAT
   ,MinData FLOAT
   ,MaxData FLOAT
   ,MedianData FLOAT
   ,Percentiles FLOAT[]
);

मैं इस टेम्प्लेट का उपयोग करके तालिका बना सकता हूं:

CREATE TABLE test OF dataset;

मैंने एपीआई में कई विकल्प देखे हैं , लेकिन मैं थोड़ा खो गया हूं। मैं यह जानना चाहूंगा कि क्या इस प्रकार को कार्य INPUT/OUTPUTमापदंडों में निर्दिष्ट करना संभव है ।

मान लीजिए कि मेरे पास एक FUNCTIONकॉल है processजो डेटासेट से रिकॉर्ड का एक नमूना प्राप्त करता है TABLE source, उन्हें संसाधित करता है और फिर TABLE sinkउसी के साथ रिटर्न करता है TYPE

क्या मैं यह जानना चाहूंगा कि क्या TYPEइस तरह का व्यवहार करना संभव है :

CREATE FUNCTION process(
    input dataset
) RETURNS dataset
AS ...

और इसे इस तरह कहा जा सकता है:

SELECT
    *
FROM
    source, process(input := source) AS sink;

मुझे आश्चर्य है कि यह PostgreSQL के साथ संभव है, और पूछें कि यह कैसे करना है। क्या आप में से किसी को पता है?


यहाँ एक MWE है जो मैं करने की कोशिश कर रहा हूँ:

DROP TABLE IF EXISTS source;
DROP FUNCTION IF EXISTS process(dataset);
DROP TYPE dataset;

CREATE TYPE dataset AS (
    id INTEGER
   ,t  TIMESTAMP
   ,x  FLOAT
);


CREATE TABLE source OF dataset;
ALTER TABLE source ADD PRIMARY KEY(Id);
INSERT INTO source VALUES
    (1, '2016-01-01 00:00:00', 10.0)
   ,(2, '2016-01-01 00:30:00', 11.0)
   ,(3, '2016-01-01 01:00:00', 12.0)
   ,(4, '2016-01-01 01:30:00',  9.0)
   ;

CREATE OR REPLACE FUNCTION process(
    _source dataset
)
RETURNS SETOF dataset
AS
$BODY$
SELECT * FROM source;
$BODY$
LANGUAGE SQL;

SELECT * FROM process(source);

लेकिन यह सफल नहीं होता है, यह ऐसा है जैसे स्रोत को SETOF RECORDSडेटासेट के प्रकार के बजाय एक स्तंभ माना जाता है ।

जवाबों:


13

_sourceजोड़ा गया MWE में आपके पैरामीटर को कहीं भी संदर्भित नहीं किया गया है। sourceफ़ंक्शन बॉडी में पहचानकर्ता के पास कोई प्रमुख अंडरस्कोर नहीं है और इसे स्वतंत्र रूप से निरंतर तालिका नाम के रूप में व्याख्या किया गया है।

इससे भी महत्वपूर्ण बात, यह वैसे भी काम नहीं करेगा। एसक्यूएल केवल डीएमएल बयानों में मानों को पैरामीटर करने की अनुमति देता है । इस संबंधित उत्तर में विवरण:

उपाय

आप अभी भी इसे EXECUTEplpgsql फ़ंक्शन के साथ गतिशील SQL का उपयोग करके काम कर सकते हैं । विवरण:

या संबंधित प्रश्नों और उत्तरों के लिए इस खोज का प्रयास करें

CREATE TYPE dataset AS (id integer, t timestamp, x float);
CREATE TABLE source OF dataset (PRIMARY KEY(Id));  -- add constraints in same command

INSERT INTO source VALUES
    (1, '2016-01-01 00:00:00', 10.0)
   ,(2, '2016-01-01 00:30:00', 11.0);

CREATE OR REPLACE FUNCTION process(_tbl regclass)
  RETURNS SETOF dataset AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || _tbl;
END
$func$  LANGUAGE plpgsql;

SELECT * FROM process('source');  -- table name as string literal 

आप किसी भी तालिका के लिए यह काम भी कर सकते हैं :

CREATE OR REPLACE FUNCTION process2(_tbl anyelement)
  RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || pg_typeof(_tbl);
END
$func$  LANGUAGE plpgsql;

SELECT * FROM process2(NULL::source);  -- note the call syntax!!

विस्तृत विवरण:


जवाब के लिए धन्यवाद। इल कुछ घंटों में इसकी जाँच करेगा। परीक्षण करने से पहले जानना, क्या आपके समाधान को पंक्तियों के रूप में स्वीकार करना है SELECT। मेरा मतलब है SELECT * FROM process((SELECT * FROM source WHERE cond))
jlandercy

@ ज: नहीं, आप एक टेबल नेम पास करते हैं । कोई तालिका स्वयं (कोई तालिका चर) पास करने का कोई तरीका नहीं है। इसके आसपास कई तरीके हैं। संबंधित: stackoverflow.com/a/27853965/939860 या stackoverflow.com/a/31167928/939860 । एक प्रश्न के परिणाम पर काम करने के लिए मैं एक कर्सर या एक अस्थायी तालिका का उपयोग करूंगा ...
Erwin Brandstetter

0

यह वह होगा जो आप किसी गतिशील SQL की आवश्यकता के बिना चाहते हैं :

drop table if exists source cascade;
drop function if exists process(dataset) cascade;
drop type if exists dataset cascade;

create type dataset as (
    id integer
   ,t  timestamp
   ,x  float
);

create table source of dataset;
alter table source add primary key(id);
insert into source values
   (1, '2016-01-01 00:00:00', 10.0)
 , (2, '2016-01-01 00:30:00', 11.0)
;

create or replace function process(
    x_source dataset[]
)
returns setof dataset
as
$body$
select * from unnest(x_source);
$body$
language sql;

select *
from
  process(
    array(
      select
        row(id, t, x)::dataset
      from source
    )
  );

जहां तक ​​मैं बता सकता हूं (गोगेलिंग के बाद बेहद, क्योंकि मुझे भी यही समस्या थी) आप किसी फंक्शन में सीधे टेबल पास नहीं कर सकते।

हालांकि, जैसा कि दिखाया गया है, आप एक तालिका को []एक कस्टम प्रकार की एक सरणी में बदल सकते हैं जिसमें कई मूल प्रकार (तालिका परिभाषा के समान) होते हैं।

फिर आप उस एरे को पास कर सकते हैं और फंक्शन में आने के बाद इसे वापस टेबल पर बेकार कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.