PostgreSQL ফাংশন প্যারামিটার হিসাবে সারণীর নাম


87

আমি পোস্টগ্রিজ ফাংশনে একটি টেবিলের নামটি প্যারামিটার হিসাবে পাস করতে চাই। আমি এই কোডটি চেষ্টা করেছি:

CREATE OR REPLACE FUNCTION some_f(param character varying) RETURNS integer 
AS $$
    BEGIN
    IF EXISTS (select * from quote_ident($1) where quote_ident($1).id=1) THEN
     return 1;
    END IF;
    return 0;
    END;
$$ LANGUAGE plpgsql;

select some_f('table_name');

এবং আমি এটি পেয়েছি:

ERROR:  syntax error at or near "."
LINE 4: ...elect * from quote_ident($1) where quote_ident($1).id=1)...
                                                             ^

********** Error **********

ERROR: syntax error at or near "."

এবং এখানে পরিবর্তন করার সময় আমি যে ত্রুটিটি পেয়েছি তা এখানে রয়েছে select * from quote_ident($1) tab where tab.id=1:

ERROR:  column tab.id does not exist
LINE 1: ...T EXISTS (select * from quote_ident($1) tab where tab.id...

সম্ভবত, quote_ident($1)কাজ করে, কারণ where quote_ident($1).id=1আমি যে অংশটি পাই তা ছাড়া 1, যার অর্থ কোনও কিছু নির্বাচিত is প্রথম quote_ident($1)কাজ এবং দ্বিতীয়টি একই সময়ে না কেন হতে পারে ? এবং কীভাবে এটি সমাধান করা যায়?


আমি জানি এই প্রশ্নটি একপ্রকার পুরানো, তবে অন্য একটি সমস্যার উত্তর খুঁজতে গিয়ে এটি খুঁজে পেয়েছি। আপনার ফাংশনটি কেবল ইনফরমালাল_স্কেমাকে জিজ্ঞাসা করতে পারেনি? আমি বোঝাতে চাইছি, এটি কোনও ধরণের জন্য কী - এটি আপনাকে জিজ্ঞাসা করতে এবং ডেটাবেসে কী কী অস্তিত্ব রয়েছে তা দেখতে দেয়। শুধু একটি ধারণা।
ডেভিড এস

@ ডেভিড একটি মন্তব্যের জন্য ধন্যবাদ, আমি এটি চেষ্টা করব।
জন দো

উত্তর:


126

এটি আরও সরলীকৃত এবং উন্নত করা যেতে পারে:

CREATE OR REPLACE FUNCTION some_f(_tbl regclass, OUT result integer)
    LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT (EXISTS (SELECT FROM %s WHERE id = 1))::int', _tbl)
   INTO result;
END
$func$;

স্কিমা-যোগ্য নামের সাথে কল করুন (নীচে দেখুন):

SELECT some_f('myschema.mytable');  -- would fail with quote_ident()

বা:

SELECT some_f('"my very uncommon table name"');

প্রধান পয়েন্ট

  • ফাংশনটি সহজ করার জন্য একটি OUTপ্যারামিটার ব্যবহার করুন । আপনি এটিতে ডায়নামিক এসকিউএল এর ফলাফলটি সরাসরি নির্বাচন করতে পারেন এবং হয়ে যায়। অতিরিক্ত ভেরিয়েবল এবং কোডের প্রয়োজন নেই।

  • EXISTSআপনি যা চান ঠিক তাই করে trueসারিটি উপস্থিত থাকলে বা falseঅন্যথায় আপনি পাবেন । এটি করার বিভিন্ন উপায় রয়েছে, EXISTSসাধারণত সবচেয়ে দক্ষ।

  • আপনি একটি চান বলে মনে হচ্ছে পূর্ণসংখ্যা , পিছনে তাই আমি নিক্ষেপ booleanথেকে ফলাফলের EXISTSজন্য integer, যা উৎপাদ তুমি আসলে কি ছিল। আমি পরিবর্তে বুলিয়ান ফিরে আসতে হবে।

  • আমি regclassইনপুট টাইপ হিসাবে অবজেক্ট আইডেন্টিফায়ার টাইপ ব্যবহার করি _tbl। এটি সবকিছু করে quote_ident(_tbl)বা format('%I', _tbl)করবে, তবে আরও ভাল, কারণ:

  • .. এটি এসকিউএল ইঞ্জেকশনটিকে ঠিক একইভাবে প্রতিরোধ করে ।

  • ..এটি অবিলম্বে এবং আরও কৃত্রিমভাবে ব্যর্থ হয় যদি টেবিলের নামটি অবৈধ / উপস্থিত না থাকে / বর্তমান ব্যবহারকারীর কাছে অদৃশ্য থাকে। (একটি regclassপরামিতি কেবল বিদ্যমান টেবিলগুলির জন্য প্রযোজ্য ))

  • .. এটি স্কিমা-যোগ্য টেবিলের নামগুলির সাথে কাজ করে, যেখানে প্লেইন quote_ident(_tbl)বা format(%I)ব্যর্থ হয় কারণ তারা অস্পষ্টতাটি সমাধান করতে পারে না। আপনাকে আলাদা করে স্কিমা এবং টেবিলের নামগুলি পাস করতে হবে এবং পালাতে হবে।

  • আমি এখনও ব্যবহার করি format(), কারণ এটি সিনট্যাক্সকে সহজতর করে (এবং এটি কীভাবে ব্যবহৃত হয় তা প্রদর্শনের জন্য), তবে %sপরিবর্তে এটি দিয়ে %I। সাধারণত, অনুসন্ধানগুলি আরও জটিল তাই format()আরও সহায়তা করে helps সরল উদাহরণের জন্য আমরা পাশাপাশি কেবল সম্মতি জানাতে পারি:

      EXECUTE 'SELECT (EXISTS (SELECT FROM ' || _tbl || ' WHERE id = 1))::int'
    
  • তালিকায় idকেবলমাত্র একটি একক সারণী থাকাকালীন কলামটি সারণি-যোগ্যতার প্রয়োজন নেই FROM। এই উদাহরণে কোনও অস্পষ্টতা সম্ভব নয়। (ডায়নামিক) ভিতরে এসকিউএল কমান্ডগুলির EXECUTEএকটি পৃথক সুযোগ রয়েছে , ফাংশন বডিটিতে প্লেইন এসকিউএল কমান্ডের বিপরীতে, ফাংশন ভেরিয়েবল বা প্যারামিটারগুলি সেখানে দৃশ্যমান নয়।

আপনি কেন ডাইনামিক এসকিউএল-এর জন্য সর্বদা ব্যবহারকারীর ইনপুটটি সঠিকভাবে এড়িয়ে যান তা এখানে :

ডিবি <> বেহালার এখানে প্রদর্শক এসকিউএল ইনজেকশন
প্রাচীন sqlfiddle


4
@ সুহপ্রানো: অবশ্যই এটি ব্যবহার করে দেখুন:DO $$BEGIN EXECUTE 'ANALYZE mytbl'; END$$;
এরউইন ব্র্যান্ডসটেটার

কেন% s এবং% এল নয়?
লোটাস

4
@ লোটাস: ব্যাখ্যাটি উত্তরে রয়েছে। regclassপাঠ্য হিসাবে আউটপুট এলে মানগুলি স্বয়ংক্রিয়ভাবে পালিয়ে যায়। এই ক্ষেত্রে ভুল%L হবে ।
এরউইন ব্র্যান্ডসটেটার

CREATE OR REPLACE FUNCTION table_rows(_tbl regclass, OUT result integer) AS $func$ BEGIN EXECUTE 'SELECT (SELECT count(1) FROM ' || _tbl || ' )::int' INTO result; END $func$ LANGUAGE plpgsql; একটি সারণী সারি গণনা ফাংশন তৈরি করুনselect table_rows('nf_part1');
ফেরিস

আমরা কীভাবে সমস্ত কলাম পেতে পারি?
আশীষ

13

যদি সম্ভব হয় তবে এটি করবেন না।

এটি উত্তর - এটি একটি বিরোধী-নিদর্শন। যদি ক্লায়েন্টটি টেবিলটি জানে তবে এটি থেকে ডেটা চায় SELECT FROM ThatTable। যদি কোনও ডাটাবেস এমনভাবে ডিজাইন করা হয় যাতে এটি প্রয়োজনীয় হয় তবে মনে হয় এটি উপ-অনুকূলভাবে ডিজাইন করা হয়েছে। যদি কোনও ডেটা অ্যাক্সেস লেয়ারটি যদি কোনও টেবিলের মধ্যে কোনও মান বিদ্যমান কিনা তা জানতে প্রয়োজন হয় তবে সেই কোডটিতে এসকিউএল রচনা করা সহজ, এবং এই কোডটিকে ডাটাবেসে ঠেলা ভাল নয় not

আমার কাছে এটি লিফ্টের অভ্যন্তরে কোনও ডিভাইস ইনস্টল করার মতো মনে হয় যেখানে পছন্দসই মেঝেতে কেউ টাইপ করতে পারে। গো বোতাম টিপে যাওয়ার পরে, এটি একটি যান্ত্রিক হাতকে পছন্দসই তলটির জন্য সঠিক বোতামের দিকে নিয়ে যায় এবং টিপে দেয়। এটি অনেক সম্ভাব্য সমস্যাগুলির পরিচয় দেয়।

দয়া করে নোট করুন: এখানে উপহাস করার কোনও উদ্দেশ্য নেই। এই নিখুঁতভাবে এই কৌশলটি দিয়ে সমস্যাগুলি ইঙ্গিত করার জন্য আমার নির্বোধ লিফ্টের উদাহরণটি ছিল * আমি সবচেয়ে সেরা ডিভাইসটি * কল্পনা করতে পারি। এটি সংক্ষিপ্ত / উদ্ভট সার্ভার-সাইড এসকিউএল কোড ব্যবহার করে একটি হাইব্রিডে কলার স্পেস থেকে টেবিলের নাম পছন্দ (একটি শক্তিশালী এবং ভালভাবে বোঝা ডিএসএল, এসকিউএল) ব্যবহার করে ইন্ডিয়ারেশনের একটি অকেজো স্তর যুক্ত করে।

গতিশীল এসকিউএল-তে ক্যোয়ারি নির্মাণ লজিকের চলাফেরার মাধ্যমে এই জাতীয় দায়িত্ব-বিভাজন কোডটিকে বোঝা আরও শক্ত করে তোলে। এটি ত্রুটির সম্ভাবনার সাথে ভরা কাস্টম কোডের নামে একটি স্ট্যান্ডার্ড এবং নির্ভরযোগ্য কনভেনশন (কীভাবে একটি এসকিউএল কোয়েরি চয়ন করবে) তা লঙ্ঘন করে।

এই পদ্ধতির সাথে কিছু সম্ভাব্য সমস্যার উপর বিশদ পয়েন্ট এখানে দেওয়া হয়েছে:

  • ডায়নামিক এসকিউএল এসকিউএল ইঞ্জেকশনটির সম্ভাবনা সরবরাহ করে যা সামনের শেষ কোড বা ব্যাক এন্ড কোডে একা সনাক্ত করা শক্ত (এটি দেখতে তাদের অবশ্যই একসাথে পরিদর্শন করতে হবে)।

  • সঞ্চিত পদ্ধতি এবং ফাংশনগুলি এমন সংস্থানগুলিতে অ্যাক্সেস করতে পারে যেগুলিতে এসপি / ফাংশনের মালিকের অধিকার রয়েছে তবে কলারের তা নেই। আমি যতদূর বুঝতে পারি, বিশেষ যত্ন ছাড়াই, তারপরে ডিফল্টরূপে আপনি যখন কোডটি ব্যবহার করেন যা গতিশীল এসকিউএল তৈরি করে এবং এটি চালায়, ডেটাবেস কলারের অধিকারের অধীনে গতিশীল এসকিউএল চালায়। এর অর্থ আপনি হয় কোনও সুবিধাযুক্ত বস্তু ব্যবহার করতে পারবেন না, বা আপনাকে এগুলি সমস্ত ক্লায়েন্টের জন্য উন্মুক্ত করতে হবে, সম্ভাব্য আক্রমণের পৃষ্ঠের ক্ষেত্রটিকে সুবিধাগুলিযুক্ত ডেটাতে বাড়িয়ে তুলতে হবে। সর্বদা নির্দিষ্ট ব্যবহারকারীর (এসকিউএল সার্ভারে EXECUTE AS) চালানোর জন্য এসপি / ফাংশন নির্ধারণের ফলে সমস্যাটি সমাধান হতে পারে তবে জিনিসগুলি আরও জটিল করে তোলে। এটি গতিশীল এসকিউএলকে খুব প্ররোচিত আক্রমণকারী ভেক্টর করে পূর্ববর্তী পয়েন্টে উল্লিখিত এসকিউএল ইঞ্জেকশনের ঝুঁকি বাড়িয়ে তোলে।

  • যখন কোনও বিকাশকারীকে বুঝতে হবে যে অ্যাপ্লিকেশন কোডটি এটি সংশোধন করতে বা কোনও ত্রুটি সংশোধন করার জন্য কী করছে, তখন সঠিক এসকিউএল কোয়েরি কার্যকর করা খুব কঠিন মনে হবে find এসকিউএল প্রোফাইলার ব্যবহার করা যেতে পারে তবে এটি বিশেষ সুবিধা নেয় এবং উত্পাদন সিস্টেমে নেতিবাচক কর্মক্ষমতা প্রভাব ফেলতে পারে। মৃত্যুদন্ডপ্রাপ্ত জিজ্ঞাসাটি এসপি দ্বারা লগইন করা যেতে পারে তবে এটি সন্দেহজনক সুবিধার জন্য জটিলতা বৃদ্ধি করে (নতুন টেবিলের সমন্বিত প্রয়োজন, পুরানো ডেটা বিশুদ্ধ করা ইত্যাদি) এবং এটি একেবারে স্পষ্ট নয়। আসলে, কিছু অ্যাপ্লিকেশনগুলি এমনভাবে আর্কিটেক্ট করা হয় যে বিকাশকারীর ডেটাবেস শংসাপত্রগুলি না থাকে, সুতরাং কোয়েরিটি জমা দেওয়া আসলে তার পক্ষে দেখা প্রায় অসম্ভব হয়ে পড়ে।

  • যখন কোনও ত্রুটি দেখা দেয়, যেমন আপনি যখন উপস্থিত নন এমন একটি টেবিল নির্বাচন করার চেষ্টা করেন তখন আপনি ডাটাবেস থেকে "অবৈধ অবজেক্টের নাম" এর লাইনে একটি বার্তা পাবেন। আপনি ঠিক পেছনের প্রান্তে বা ডাটাবেসটিতে এসকিউএল রচনা করছেন কিনা তা ঠিক একই ঘটবে তবে পার্থক্যটি হ'ল কিছু দুর্বল বিকাশকারী যিনি সিস্টেমটির সমস্যা সমাধানের চেষ্টা করছেন তার একের নিচে অন্য একটি গুহায় এক স্তর আরও গভীরভাবে ছড়িয়ে দিতে হবে যেখানে সমস্যাটি রয়েছে, বিস্ময়কর পদ্ধতিটি খনন করতে সমস্যাটি কী তা বোঝার চেষ্টা করার চেষ্টা করে। লগগুলি "গেটউইজেটে ত্রুটি" দেখাবে না, এটি "ওয়ানপ্রসেসটোটোরুলেটেমালআররনারে ত্রুটি" প্রদর্শন করবে। এই বিমূর্ততা সাধারণত একটি সিস্টেমকে আরও খারাপ করে দেবে

প্যারামিটারের উপর ভিত্তি করে টেবিলের নাম স্যুইচ করা সিউডো-সি # এর একটি উদাহরণ:

string sql = $"SELECT * FROM {EscapeSqlIdentifier(tableName)};"
results = connection.Execute(sql);

যদিও এটি প্রতিটি সম্ভাব্য সমস্যাটি কল্পনাপ্রসূতভাবে দূর করে না, অন্য কৌশলগুলির সাথে আমি যে ত্রুটিগুলি উল্লেখ করেছি সেগুলি এই উদাহরণ থেকে অনুপস্থিত।


4
আমি এর সাথে পুরোপুরি একমত হই না। বলুন, আপনি এই "গো" বোতামটি টিপুন এবং তারপরে মেঝেটি উপস্থিত থাকলে কিছু প্রক্রিয়া পরীক্ষা করে। ট্রিগারগুলিতে ফাংশনগুলি ব্যবহার করা যেতে পারে যা ফলস্বরূপ কিছু শর্তগুলি পরীক্ষা করতে পারে। এই বর্ণনাটি সর্বাধিক সুন্দর নাও হতে পারে, তবে যদি সিস্টেমটি ইতিমধ্যে যথেষ্ট বড় হয় এবং আপনার যুক্তিতে কিছু সংশোধন করা দরকার, ভাল, এই পছন্দটি এত নাটকীয় নয়, আমার ধারণা।
জন দো

4
তবে বিবেচনা করুন যে অস্তিত্ব নেই এমন একটি বোতাম টিপতে চেষ্টা করার ক্রিয়াটি কেবল আপনি কীভাবে এটি পরিচালনা করবেন না কেন কেবল ব্যতিক্রম তৈরি করবে। আপনি আসলে একটি অস্তিত্বহীন বোতাম টিপতে পারবেন না, সুতরাং বোতাম-পুশিংয়ের শীর্ষে অস্তিত্বহীন সংখ্যাগুলি পরীক্ষা করার জন্য একটি স্তর যুক্ত করার কোনও সুবিধা নেই, কারণ স্তরটি তৈরির আগে আপনি যেমন সংখ্যা এন্ট্রি উপস্থিত ছিলেন না! বিমূর্ততা আমার মতে প্রোগ্রামিংয়ের সবচেয়ে শক্তিশালী সরঞ্জাম। যাইহোক, একটি স্তর যে নিছক দুর্বল একটি বিদ্যমান বিমূর্ততা সদৃশ যোগ হয় ভুল । ডাটাবেস নিজেই ইতিমধ্যে একটি বিমূর্ত স্তর যা ডেটা সেটগুলিতে নাম মানচিত্র করে।
এরিক

4
চিহ্নিত করা. এসকিউএল এর সম্পূর্ণ বিন্দুটি হ'ল আপনি যে ডেটা উত্তোলন করতে চান তার সেট প্রকাশ করা। এই ফাংশনটি কেবলমাত্র একটি "ক্যানড" এসকিউএল স্টেটমেন্ট encapsulate হয়। সনাক্তকারীটি কঠোরভাবে কোডড হওয়া এই বিষয়টিটি দেওয়াতে এটির দুর্গন্ধ রয়েছে।
নিক হ্রিস্টভ

4
@ ততক্ষণ কেউ দক্ষতার দক্ষতার পর্বে ( দক্ষতা অর্জনের Dreyfus মডেল দেখুন ) না হওয়া পর্যন্ত তাকে অবশ্যই "ডাইনামিক এসকিউএল ব্যবহারের পদ্ধতিতে টেবিলের নামগুলি পাস করবেন না" এর মতো নিয়মগুলি পুরোপুরি মেনে চলতে হবে। এমনকি এটি সর্বদা খারাপ হয় না এমন ইঙ্গিত দেওয়া নিজেই খারাপ পরামর্শ । এটি জানতে পেরে, শিক্ষানবিস এটি ব্যবহারের জন্য প্রলুব্ধ হবে! এটা খারাপ. কোনও বিষয়ের কেবলমাত্র মাস্টারদেরই নিয়মগুলি ভঙ্গ করা উচিত, কারণ এই নিয়ম-ভাঙ্গা আসলেই বোধগম্যতা লাভ করে কিনা তা কোনও নির্দিষ্ট ক্ষেত্রেই তারা অভিজ্ঞতার সাথে অভিজ্ঞতার সাথে রয়েছে।
এরিক

4
@ থ্রি-কাপগুলি কেন এটি খারাপ ধারণা সে সম্পর্কে আরও অনেক বিশদ দিয়ে আপডেট করেছি।
এরিক

10

ভিতরে plpgsql কোড, দি সারণীর নাম বা কলামগুলি ভেরিয়েবল থেকে আসে এমন প্রশ্নের জন্য অবশ্যই EXECUTE বিবৃতি ব্যবহার করা উচিত। এছাড়াও IF EXISTS (<query>)যখন queryগতিশীলভাবে উত্পন্ন হয় তখন নির্মাণের অনুমতি দেওয়া হয় না ।

উভয় সমস্যার সমাধান সহ আপনার ফাংশন এখানে:

CREATE OR REPLACE FUNCTION some_f(param character varying) RETURNS integer 
AS $$
DECLARE
 v int;
BEGIN
      EXECUTE 'select 1 FROM ' || quote_ident(param) || ' WHERE '
            || quote_ident(param) || '.id = 1' INTO v;
      IF v THEN return 1; ELSE return 0; END IF;
END;
$$ LANGUAGE plpgsql;

ধন্যবাদ, আমি আপনার উত্তরটি পড়ার কয়েক মিনিট আগে ঠিক একই রকম করেছিলাম। কেবলমাত্র quote_ident()তফাতটিই আমাকে সরাতে হয়েছিল কারণ এটি অতিরিক্ত উদ্ধৃতি যুক্ত করেছে, যা আমাকে খানিকটা অবাক করেছিল, 'বেশিরভাগ উদাহরণে এটি ব্যবহৃত হয় cause
জন দো

যদি / যখন টেবিলের নামটিতে [অ্যাজ] বাইরের অক্ষর থাকে তবে বা / যখন এটি কোনও সংরক্ষিত শনাক্তকারীর সাথে সংঘর্ষ হয় (উদাহরণস্বরূপ: টেবিলের নাম হিসাবে "গোষ্ঠী")
ড্যানিয়েল ভ্যারিটি

এবং, যাইহোক, আপনি দয়া করে একটি লিঙ্ক সরবরাহ করতে পারেন যা প্রমাণ করবে যে IF EXISTS <query>নির্মাণের অস্তিত্ব নেই? আমি নিশ্চিত যে আমি ওয়ার্কিং কোডের নমুনা হিসাবে এরকম কিছু দেখেছি।
জন দো

4
@ জনডো: পি এল পি এস এস এস এল-এ IF EXISTS (<query>) THEN ...সম্পূর্ণরূপে বৈধ নির্মাণ। গতিশীল এসকিউএল জন্য ঠিক না <query>। আমি এটি অনেক ব্যবহার করি। এছাড়াও, এই ফাংশনটি কিছুটা উন্নত করা যেতে পারে। আমি একটি উত্তর পোস্ট।
এরউইন ব্র্যান্ডসেটেটার

4
দুঃখিত, আপনি ঠিক বলেছেন if exists(<query>), এটি সাধারণ ক্ষেত্রে কার্যকর। সবেমাত্র উত্তরটি যাচাই করা হয়েছে এবং সেই অনুসারে সংশোধন করা হয়েছে।
ড্যানিয়েল ভ্যারিট

4

প্রথমটি আপনার বোঝার অর্থে আসলে "কাজ" করে না, এটি ততক্ষণ কাজ করে কারণ এটি ত্রুটি তৈরি করে না।

চেষ্টা করুন SELECT * FROM quote_ident('table_that_does_not_exist');, এবং আপনি দেখতে পাবেন কেন আপনার ফাংশনটি 1 টি ফেরায়: নির্বাচিতরা quote_identএকটি সারি (পরিবর্তনশীল $1বা এই বিশেষ ক্ষেত্রে table_that_does_not_exist) সহ একটি কলাম (নামযুক্ত ) দিয়ে একটি টেবিল ফিরিয়ে দিচ্ছে ।

আপনি যা করতে চান তার জন্য গতিশীল এসকিউএল প্রয়োজন হবে, যা কার্যত যে স্থানটি quote_*ব্যবহৃত হবে তা বোঝানো হচ্ছে।


অনেক অনেক ধন্যবাদ, ম্যাট, table_that_does_not_existএকই ফলাফল দিয়েছে, আপনি ঠিক বলেছেন।
জন দো

2

যদি প্রশ্নটি পরীক্ষা করা হয় যে টেবিলটি খালি রয়েছে বা না (আইডি = 1), এখানে ইরভিনের সঞ্চিত প্রোকরের একটি সরল সংস্করণ দেওয়া হয়েছে:

CREATE OR REPLACE FUNCTION isEmpty(tableName text, OUT zeroIfEmpty integer) AS
$func$
BEGIN
EXECUTE format('SELECT COALESCE ((SELECT 1 FROM %s LIMIT 1),0)', tableName)
INTO zeroIfEmpty;
END
$func$ LANGUAGE plpgsql;

1

আমি জানি এটি একটি পুরানো থ্রেড, তবে সম্প্রতি একই সমস্যাটি সমাধান করার চেষ্টা করার সময় আমি এটি পেরিয়ে এসেছি - আমার ক্ষেত্রে কিছু জটিল জটিল স্ক্রিপ্টগুলির জন্য।

পুরো স্ক্রিপ্টটিকে ডায়নামিক এসকিউএল রূপান্তর করা আদর্শ নয়। এটি ক্লান্তিকর এবং ত্রুটি-প্রবণ কাজ এবং আপনি প্যারামিটারাইজ করার ক্ষমতা হারাবেন: পারফরম্যান্সগুলি এসকিউএল-এ ধ্রুবকগুলিতে বিভক্ত করা উচিত, কর্মক্ষমতা এবং সুরক্ষার জন্য খারাপ পরিণতি সহ with

এখানে একটি সহজ কৌশল যা আপনাকে কেবলমাত্র আপনার টেবিল থেকে বাছাই করতে হবে যদি আপনি এসকিউএল অক্ষত রাখতে চান - একটি অস্থায়ী ভিউ তৈরি করতে গতিশীল এসকিউএল ব্যবহার করুন:

CREATE OR REPLACE FUNCTION some_f(_tbl varchar) returns integer
AS $$
BEGIN
    drop view if exists myview;
    execute format('create temporary view myview as select * from %s', _tbl);
    -- now you can reference myview in the SQL
    IF EXISTS (select * from myview where myview.id=1) THEN
     return 1;
    END IF;
    return 0;
END;
$$ language plpgsql;

0

আপনি যদি টেবিলের নাম, কলামের নাম এবং মানটি পরিবর্তনশীলভাবে প্যারামিটার হিসাবে কাজ করতে চান

এই কোড ব্যবহার করুন

create or replace function total_rows(tbl_name text, column_name text, value int)
returns integer as $total$
declare
total integer;
begin
    EXECUTE format('select count(*) from %s WHERE %s = %s', tbl_name, column_name, value) INTO total;
    return total;
end;
$total$ language plpgsql;


postgres=# select total_rows('tbl_name','column_name',2); --2 is the value

-2

আমার পোস্টগ্রিজ এসকিউএল এর 9.4 সংস্করণ রয়েছে এবং আমি সর্বদা এই কোডটি ব্যবহার করি:

CREATE FUNCTION add_new_table(text) RETURNS void AS
$BODY$
begin
    execute
        'CREATE TABLE ' || $1 || '(
        item_1      type,
        item_2      type
        )';
end;
$BODY$
LANGUAGE plpgsql

এবং তারপর:

SELECT add_new_table('my_table_name');

এটি আমার পক্ষে ভাল কাজ করে।

মনোযোগ! উপরের উদাহরণগুলির মধ্যে একটি যা দেখায় যে "ডাটাবেস অনুসন্ধানের সময় আমরা সুরক্ষা রাখতে চাইলে কীভাবে হয় না": পি


4
একটি newসারণী তৈরি করা বিদ্যমান টেবিলের নামের সাথে অপারেটিং থেকে আলাদা। যে কোনও উপায়ে আপনার কোড হিসাবে সম্পাদিত পাঠ্য পরামিতিগুলি এড়ানো উচিত বা আপনি এসকিউএল ইঞ্জেকশনটিতে খোলা রয়েছেন।
এরউইন ব্র্যান্ডসেটেটার

ওহ, হ্যাঁ, আমার ভুল বিষয়টি আমাকে বিভ্রান্ত করেছে এবং উপরন্তু আমি এটি শেষ পর্যন্ত পড়িনি। সাধারণত আমার ক্ষেত্রে। : P কেন একটি পাঠ্য প্যারামিটার সহ কোডটি ইনজেকশনের সংস্পর্শে আসে?
dm3

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