আমি কীভাবে PL / pgSQL এ একাধিক সারি রেকর্ড ফিরিয়ে দিতে পারি


14

আমি রেকর্ড ডেটা টাইপ ব্যবহার করে একাধিক রেকর্ড ফিরিয়ে দেওয়ার চেষ্টা করছি, এমন কোনও উপায় আছে যা আমি এই রেকর্ডের সাথে প্রতিটি পুনরাবৃত্তির সাথে একটি নতুন মান যুক্ত / যুক্ত করতে পারি R

এটি হল, আমি যুক্ত করতে চাই recযাতে recলুপটি শেষ হয়ে গেলে সারিগুলির একটি সেট হয়ে যায়, যা আমি আমার ফাংশনটির শেষে ফিরে আসতে পারি। বর্তমানে, আমি এটি করছি -

SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;

আমার সম্পূর্ণ কোড এখানে:

CREATE OR REPLACE FUNCTION validation()
  RETURNS RECORD AS $$
DECLARE
        rec RECORD;
        temp_row RECORD;
BEGIN

  CREATE TEMPORARY TABLE temp_table (col1 TEXT, col2 INTEGER, col3 BOOLEAN) ON COMMIT DROP;

  FOR temp_row IN SELECT * FROM staging.validation
  LOOP

    RAISE NOTICE 'sql: %', temp_row.sql;

    EXECUTE format('INSERT INTO temp_table %s', temp_row.sql);

    IF (SELECT DISTINCT temp_table.col3 FROM temp_table WHERE temp_table.col3 = false)=false THEN
      RAISE NOTICE 'there is a false value';

      SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;
    END IF;


  END LOOP;
  RETURN rec;
END; $$
LANGUAGE plpgsql;

বর্তমান আউটপুট পরে SELECT validation();

validation
(crea_ddf,8095,f)

পছন্দসই আউটপুট

validation
(crea_ddf,8095,f)
(some_source_system,some_count,f)
(some_other_source_system,some_count,f)
(.....)

@ ইভানক্রোল হাই ইভান, এটি আমার প্রশ্ন, যা আমি সেখানেও পোস্ট করেছি ... যদি কেউ এখানে এটি মিস করে তবেই।
hky404

আমি নিশ্চিত না আপনি যা করার চেষ্টা করছেন, আপনি কি আরও কিছুটা ব্যাখ্যা করতে পারেন?
ইভান ক্যারল

1
@ hky404: দয়া করে ক্রস পোস্ট করবেন না; যা কেবলমাত্র চেষ্টাগুলির অনুলিপি তৈরি করে।
মার্টিজন পিটারস

উত্তর:


14

ফাংশনটির SETOF RECORDপরিবর্তে একটি পরিবর্তিত হওয়া RECORDএবং RETURN NEXTএককটির পরিবর্তে সারি প্রতি একটি RETURNথাকা দরকার:

CREATE FUNCTION test() RETURNS SETOF RECORD AS $$
DECLARE
 rec record;
BEGIN
  select 1,2 into rec;
  return next rec;

  select 3,4 into rec;
  return next rec;
END $$ language plpgsql;

কলার:

=> এক্স (হিসাবে একটি int, বি int) হিসাবে পরীক্ষা () থেকে * নির্বাচন করুন;
 ক | খ
--- + + ---
 1 | 2
 3 | 4
(২ টি সারি)

নোট করুন যে এসকিউএল দৃ strongly় এবং স্থিতিশীলভাবে টাইপ করা হচ্ছে, RECORDসিউডো-টাইপটি কাজ করা কঠিন।
প্রায়শই এটি নাম থেকে সম্পূর্ণ সংজ্ঞা এবং প্রতিটি কলামের TABLE(...)জন্য টাইপ করে কোনও বেনামে টাইপের জন্য সিনট্যাক্স সহ বা CREATE TYPEঅবিচ্ছিন্ন নামযুক্ত টাইপের সাথে মিশ্রিত টাইপটি শুরু থেকেই ব্যবহার করা কম জটিল ।


8

ব্যবহার করুন setof recordএবং return next recযদি আপনি কোনও ফাংশন থেকে একাধিক রেকর্ড ফিরিয়ে দিতে চান, উদাহরণস্বরূপ:

create or replace function test_function()
    returns setof record 
    language plpgsql as $$
declare
    rec record;
begin
    for rec in
        select i, format('str%s', i), i/2*2 = i
        from generate_series(1, 3) i
    loop
        return next rec;
    end loop;
end $$;

এই জাতীয় ক্রিয়াকলাপটি একটি কলাম সংজ্ঞা তালিকা সহ FROM ধারাতে কল করা প্রয়োজন:

select test_function(); -- NO

ERROR:  set-valued function called in context that cannot accept a set  

select * from test_function();  -- NO

ERROR:  a column definition list is required for functions returning "record"

select * from test_function() as (id int, str text, is_even boolean);

 id | str  | is_even 
----+------+---------
  1 | str1 | f
  2 | str2 | t
  3 | str3 | f
(3 rows)

আরও ভাল বিকল্পটি ব্যবহার করা returns table(...)এবং return query:

drop function if exists test_function();
create or replace function test_function()
    returns table (id int, str text, is_even boolean)
    language plpgsql as $$
begin
    return query
        select i, format('str%s', i), i/2*2 = i
        from generate_series(1, 3) i;
    -- you can use return query multiple times
    -- or assign values to columns
    -- and return the row:
    id = 100;
    str = 'extra';
    is_even = true;
    return next; -- without a parameter
end $$;

ব্যবহার:

select test_function(); -- possible but rather impractical

 test_function 
---------------
 (1,str1,f)
 (2,str2,t)
 (3,str3,f)
 (100,extra,t)
(4 rows)

select * from test_function();

 id  |  str  | is_even 
-----+-------+---------
   1 | str1  | f
   2 | str2  | t
   3 | str3  | f
 100 | extra | t
(4 rows)

1

এটি একটি লাল পতাকা ..

  1. আপনি একটি টেবিল আছে validation
  2. আপনি সারিগুলি একটি টেম্প টেবিলের মধ্যে সরিয়ে নিন staging
  3. কোনও temp_table.col3IS FALSE সহ যে কোনও সারি আপনি ব্যবহারকারীর কাছে ফিরে যান
  4. সারণির একটি নির্দিষ্ট তালিকার অন্য যে কোনও সারি সহ যেখানে কলামটি মিথ্যা।
  5. তারপরে আপনি টেম্প টেবিলটি ছেড়ে দিন

শুধু এই ..

WITH t AS ( SELECT true AS runthis FROM staging.validation WHERE col3 IS FALSE )
SELECT *
FROM staging.validation
WHERE t.runthis && col3 = 3
UNION ALL 
  SELECT *
  FROM some_source_system
  WHERE t.runthis && some_source_system.col3 = 3
UNION ALL 
  SELECT *
  FROM some_other_source_system
  WHERE t.runthis && some_other_source_system.col3 = 3;

আপনি চাইলে এটি একটিতেও রাখতে VIEWপারেন

পার্শ্ব নোট হিসাবে

SELECT DISTINCT temp_table.col3
FROM temp_table
WHERE temp_table.col3 = false

কী DISTINCTকি এখানে আছে? শুধু একটি সীমাবদ্ধ করুন। আসলে, আমি যুক্তি দেব যে এটি আরও পরিষ্কার।

SELECT true
FROM temp_table
WHERE temp_table.col3 = false
LIMIT 1;

তাহলে আপনার অদ্ভুত দরকার নেই = false ) = FALSE

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.