PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

PostgreSQL में सर्वर-साइड प्रोग्रामिंग का अवलोकन

ऐसे कई तरीके हैं जिनसे आप पोस्टग्रेज सर्वर को पूर्व-निर्धारित कोड चलाने के लिए प्राप्त कर सकते हैं। नीचे एक व्यापक सूची है, उदाहरणों के साथ, उन तरीकों की, जिनसे आप पोस्टग्रेज सर्वर को पूर्व-निर्धारित तर्क को स्टोर करने दे सकते हैं, जिसे आप बाद में अपने एप्लिकेशन से उपयोग कर सकते हैं।

एसक्यूएल फंक्शंस

पोस्टग्रेज आपको "उपयोगकर्ता-परिभाषित फ़ंक्शन" बनाने देता है, जहां फ़ंक्शन बॉडी को एक समर्थित भाषा में लिखा जा सकता है। "एसक्यूएल फंक्शंस" नियमित एसक्यूएल में लिखे गए उपयोगकर्ता-परिभाषित कार्य हैं, जो जटिल प्रश्नों और एसक्यूएल स्टेटमेंट के अनुक्रमों को समाहित करने का सबसे आसान तरीका है।

यहां कुछ उदाहरण दिए गए हैं:

-- update item price and record the change
CREATE FUNCTION update_price(item text, newprice numeric) RETURNS void AS $$
    UPDATE items SET price=$2 WHERE name=$1;
    INSERT INTO audit (event, new_price, at, item)
      VALUES ('price changed', $2, now(), $1);
$$ LANGUAGE SQL;

-- a function from uuid-osp
CREATE FUNCTION uuid_timestamp_bits(uuid) RETURNS varbit AS
$$ SELECT ('x' || substr($1::text, 15, 4) || substr($1::text, 10, 4) ||
           substr($1::text, 1, 8) || substr($1::text, 20, 4))::bit(80)
          & x'0FFFFFFFFFFFFFFF3FFF' $$
LANGUAGE SQL STRICT IMMUTABLE;

SQL फ़ंक्शन आधार प्रकार, समग्र प्रकार और पंक्तियों को स्वीकार और वापस कर सकते हैं। वे तर्कों की चर संख्या, तर्कों के लिए डिफ़ॉल्ट मान और बहुरूपी तर्कों का भी समर्थन करते हैं। वे एक तालिका से SELECTfrom की नकल करते हुए कई पंक्तियों को भी वापस कर सकते हैं। उनके लिए कुछ भी लौटाना भी आवश्यक नहीं है।

फ़ंक्शन बॉडी में केवल SQL कथन हो सकते हैं। इसका मतलब है कि कोई प्रवाह नियंत्रण विवरण नहीं हैं (यदि, जबकि, ...), चर और इसी तरह।

फ़ंक्शन बनाने के लिए CREATE FUNCTIONcommand का उपयोग किया जाता है। हमेशा की तरह, आप उन्हें बदल सकते हैं और छोड़ सकते हैं।

आगे खुदाई शुरू करने के लिए यह एक बेहतरीन जगह है:https://www.postgresql.org/docs/current/xfunc-sql.html

C फंक्शन्स

जबकि SQL फ़ंक्शन लिखने में सबसे आसान और कम से कम शक्तिशाली हैं, स्पेक्ट्रम के दूसरे छोर पर, फ़ंक्शन C में लिखे जा सकते हैं और बहुत कुछ कर सकते हैं। इस तरह के कार्यों को सी में कोडित करने और एक साझा पुस्तकालय के रूप में निर्मित करने की आवश्यकता होती है जिसे पोस्टग्रेज द्वारा गतिशील रूप से लोड किया जा सकता है।

आपको पोस्टग्रेज़ को यह बताना होगा कि साझा लाइब्रेरी को कहाँ लोड करना है, फ़ंक्शन का नाम और हस्ताक्षर:

CREATE FUNCTION sum(integer, integer) RETURNS integer
    AS 'myfuncs', 'sum'
    LANGUAGE C STRICT;

यह कहता है कि साझा पुस्तकालय myfuncs.so , एक पूर्व-निर्धारित खोजपथ में मौजूद है, जिसमें प्रवेश बिंदु होते हैं जिन्हें पोस्टग्रेज़ द्वारा बुलाया जा सकता है, जिसमें से एक प्रवेश बिंदु 'योग' होता है जिसे एक फ़ंक्शन के रूप में लागू किया जा सकता है।

सी में वास्तविक कोड यहां शामिल करने के लिए बहुत लंबा होगा, लेकिन आप दस्तावेज़ों में इसके बारे में सब कुछ पढ़ सकते हैं। सर्वर प्रोग्रामिंग इंटरफेस (एसपीआई) के साथ संयुक्त, लगभग कोई भी ऑपरेशन करना संभव है जो आप किसी अन्य तरीके से कर सकते हैं।

उदाहरण के लिए, यहां परिभाषित सी कार्यों के साथ, आप HTTP अनुरोध कर सकते हैं:

SELECT status, content_type FROM http_get('https://postgresql.org/');

ऐसी साझा पुस्तकालयों को सी++ या गो जैसी अन्य भाषाओं में लिखना भी संभव है, जो "सी" लिंकेज के साथ साझा पुस्तकालयों का निर्माण कर सकते हैं।

PL/pgSQL फ़ंक्शन

SQL और C के अलावा, आप प्रक्रियात्मक भाषाओं . में फंक्शन लिख सकते हैं . चार ऐसी भाषाएं कोर पोस्टग्रेएसक्यूएल - पीजीएसक्यूएल, पायथन, पर्ल और टीसीएल द्वारा समर्थित हैं। किसी भी प्रक्रियात्मक भाषा के लिए समर्थन स्वयं सी साझा पुस्तकालय से आता है, और mod_perl की तरह संचालित होता है। या mod_python अपाचे युग से।

पीजीएसक्यूएल विहित, सबसे अधिक उपयोग की जाने वाली, SQL जैसी भाषा है जिसमें PostgreSQL के लिए संग्रहीत कार्य लिखे जाते हैं। यह डिफ़ॉल्ट रूप से उपलब्ध है, इसके सौजन्य से template1 . में स्थापित किया जा रहा है ।

PL/pgSQL एक पूर्ण विकसित भाषा है जिसमें चर, भाव और नियंत्रण कथन हैं; और इसमें विशेष रूप से SQL डेटा के साथ काम करने के लिए कर्सर जैसी सुविधाएँ शामिल हैं। इसे यहां व्यापक रूप से प्रलेखित किया गया है।

यहां एक उदाहरण दिया गया है:

CREATE FUNCTION repeat(times integer, s text)
    RETURNS text
    AS $$
DECLARE
    result text;
BEGIN
    result := '';
    FOR i IN 1..times LOOP
        result := result || s;
    END LOOP;
    RETURN result;
END;
$$
LANGUAGE plpgsql
IMMUTABLE;

-- psql> SELECT repeat(10, '*');
--    repeat
-- ------------
--  **********
-- (1 row)

अन्य मुख्य प्रक्रियात्मक भाषाएं

अन्य प्रक्रियात्मक भाषाएं - पायथन, पर्ल, टीसीएल - डेवलपर्स को एक ऐसी भाषा का उपयोग करने की अनुमति देती हैं जिसके साथ वे पहले से ही सहज हैं। हालांकि इन भाषाओं के लिए समर्थन पोस्टग्रेज सोर्स ट्री में रहते हैं, वितरण आमतौर पर बायनेरिज़ को डिफ़ॉल्ट रूप से स्थापित नहीं करते हैं। उदाहरण के लिए, डेबियन में आपको यह करना पड़ सकता है:

sudo apt install postgresql-plpython-11

PostgreSQL 11 के लिए PL/Python समर्थन स्थापित करने के लिए।

किसी फ़ंक्शन को लिखने के लिए आप जिस भी भाषा का उपयोग कर रहे हैं, कॉलर को उसके उपयोग में कोई अंतर नहीं लगता है।

पायथन

PL/Python एक्सटेंशन Python 2 और Python 3 में लेखन कार्यों का समर्थन करता है। इसे स्थापित करने के लिए, यह करें:

CREATE EXTENSION plpythonu;

यहाँ PL/Python में लिखा गया एक फंक्शन है:

CREATE FUNCTION pymax (a integer, b integer)
  RETURNS integer
AS $$
  if a > b:
    return a
  return b
$$ LANGUAGE plpythonu;

फ़ंक्शन बॉडी में चलने वाले पायथन वातावरण में एक मॉड्यूल होता है जिसे plpy . कहा जाता है स्वचालित रूप से इसमें आयात किया जाता है। इस मॉड्यूल में वे विधियां हैं जो आपको क्वेरी तैयार करने और चलाने, लेनदेन को संभालने और कर्सर के साथ काम करने देती हैं।

अधिक जानकारी पोस्टग्रेज डॉक्स के अध्याय 46 में पाई जा सकती है।

पर्ल

खैर, हाँ, पर्ल। पोस्टग्रेज विकास, परीक्षण और निर्माण प्रक्रियाएं Perlextensively का उपयोग करती हैं, और यह एक प्रक्रियात्मक भाषा के रूप में भी समर्थित है। इसका उपयोग शुरू करने के लिए, सुनिश्चित करें कि आपके डिस्ट्रो के लिए कोई प्रासंगिक बाइनरी पैकेज स्थापित है (उदाहरण के लिए डेबियन के लिए "postgresql-plperl-nn") और एक्सटेंशन "plperl" स्थापित करें।

पीएल/पर्ल में लिखा गया एक फ़ंक्शन यहां दिया गया है:

CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
    my ($x, $y) = @_;
    if (not defined $x) {
        return undef if not defined $y;
        return $y;
    }
    return $x if not defined $y;
    return $x if $x > $y;
    return $y;
$$ LANGUAGE plperl;

पूर्ण दस्तावेज़ यहाँ।

टीसीएल

टीसीएल कोर पोस्टग्रेस द्वारा समर्थित एक और पीएल है। यहां एक उदाहरण दिया गया है:

CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
    if {[argisnull 1]} {
        if {[argisnull 2]} { return_null }
        return $2
    }
    if {[argisnull 2]} { return $1 }
    if {$1 > $2} {return $1}
    return $2
$$ LANGUAGE pltcl;

अधिक जानकारी के लिए, दस्तावेज़ यहाँ देखें।

गैर-कोर प्रक्रियात्मक भाषाएं

इन भाषाओं के अलावा, ओपन सोर्स प्रोजेक्ट हैं जो जावा, लुआ, आर आदि जैसे अन्य लोगों के लिए समर्थन विकसित और बनाए रखते हैं।

यहां एक सूची है:https://www.postgresql.org/docs/current/external-pl.html

एग्रीगेट फ़ंक्शंस

एग्रीगेट फ़ंक्शंस मानों के एक सेट पर काम करते हैं, और एक परिणाम लौटाते हैं। PostgreSQL में बिल्ट-इन एग्रीगेट फ़ंक्शंस का एक समूह है (यहां एक पूरी सूची देखें)। उदाहरण के लिए, एक कॉलम में सभी मानों का जनसंख्या मानक विचलन प्राप्त करने के लिए, आप कर सकते हैं:

SELECT stddev_pop(grade) FROM students;

आप अपने स्वयं के समग्र कार्यों को परिभाषित कर सकते हैं जो समान रूप से व्यवहार करते हैं। उपयोगकर्ता-परिभाषित समुच्चय को कुछ अलग-अलग स्टैंडअलोन फ़ंक्शंस से इकट्ठा किया जाता है जो आंतरिक स्थिति पर काम करते हैं (उदाहरण के लिए, औसत की गणना करने वाले कुल की आंतरिक स्थिति "योग" और "गणना" चर हो सकती है)।

यहां एक उपयोगकर्ता-परिभाषित समुच्चय है जो मानों के एक समूह के माध्यिका की गणना करता है:

-- from https://wiki.postgresql.org/wiki/Aggregate_Median
CREATE OR REPLACE FUNCTION _final_median(NUMERIC[])
   RETURNS NUMERIC AS
$$
   SELECT AVG(val)
   FROM (
     SELECT val
     FROM unnest($1) val
     ORDER BY 1
     LIMIT  2 - MOD(array_upper($1, 1), 2)
     OFFSET CEIL(array_upper($1, 1) / 2.0) - 1
   ) sub;
$$
LANGUAGE 'sql' IMMUTABLE;
 
CREATE AGGREGATE median(NUMERIC) (
  SFUNC=array_append,
  STYPE=NUMERIC[],
  FINALFUNC=_final_median,
  INITCOND='{}'
);

जिसे इस प्रकार कहा जा सकता है:

SELECT median(grade) FROM students;

अधिक जानकारी के लिए, एग्रीगेट के बारे में डॉक्स और क्रिएट एग्रीगेट स्टेटमेंट देखें।

उपयोगकर्ता-परिभाषित प्रकार

सी में लिखे गए साझा पुस्तकालय जो हमने पहले देखे थे, न केवल कार्यों को परिभाषित कर सकते हैं, बल्कि डेटा प्रकार भी परिभाषित कर सकते हैं। इन उपयोगकर्ता-परिभाषित प्रकारों का उपयोग स्तंभों के लिए डेटा प्रकारों के रूप में किया जा सकता है जैसे कि अंतर्निहित प्रकार। आप अपने उपयोगकर्ता-परिभाषित प्रकारों के मानों के साथ कार्य करने के लिए फ़ंक्शन को परिभाषित कर सकते हैं।

एक नए प्रकार को परिभाषित करने में थोड़ा सा कोड लगता है। जटिल संख्याओं का प्रतिनिधित्व करने के लिए एक नया प्रकार बनाने के माध्यम से आपको यहां दस्तावेज़ देखें। ThePostgres स्रोत में इसके लिए ट्यूटोरियल कोड भी शामिल है।

ऑपरेटर

ऑपरेटर फ़ंक्शन को उपयोग में आसान बनाते हैं (उदाहरण के लिए, 1 + 2 . लिखना) इसके बजाय sum(1, 2) ), और आप क्रिएट ऑपरेटर स्टेटमेंट का उपयोग करके उपयोगकर्ता-परिभाषित प्रकारों के लिए ऑपरेटरों को परिभाषित कर सकते हैं।

+ . बनाने के लिए यहां एक उदाहरण दिया गया है ऑपरेटर जो फ़ंक्शन को मैप करता हैcomplex_add जो दो complex . जोड़ता है नंबर:

CREATE OPERATOR + (
    leftarg = complex,
    rightarg = complex,
    function = complex_add,
    commutator = +
);

अधिक जानकारी यहाँ और यहाँ।

संचालक वर्ग और संचालिका परिवार

ऑपरेटर कक्षाएं आपके डेटा प्रकार को अंतर्निहित बी-ट्री और अन्य अनुक्रमण विधियों के साथ काम करने देती हैं। उदाहरण के लिए, यदि आप "कॉम्प्लेक्स" प्रकार के कॉलम पर बी-ट्री इंडेक्स बनाना चाहते हैं, तो आपको पोस्टग्रेज़ को यह बताना होगा कि इस प्रकार के दो मानों की तुलना कैसे करें, यह निर्धारित करने के लिए कि क्या एक दूसरे से कम, बराबर या बड़ा है।

यह अच्छा होगा कि जटिल प्रकारों की तुलना पूर्णांकों या फ़्लोटिंग पॉइंटवैल्यू से की जाए, जहां ऑपरेटर परिवार आते हैं।

आप यहां ऑपरेटर कक्षाओं और परिवारों के बारे में सब कुछ पढ़ सकते हैं।

ट्रिगर

ट्रिगर सामान्य ऑपरेशन के लिए साइड-इफेक्ट्स पैदा करने के लिए एक शक्तिशाली तंत्र हैं, हालांकि वे अत्यधिक उपयोग या दुरुपयोग होने पर खतरनाक हो सकते हैं। अनिवार्य रूप से, ट्रिगर घटनाओं को कार्यों से जोड़ते हैं। संदर्भित फ़ंक्शन को लागू किया जा सकता है:

  • तालिका की एक पंक्ति डालने/अपडेट/डिलीट करने से पहले या बाद में
  • टेबल को छोटा करने पर
  • दृश्य की एक पंक्ति डालने/अपडेट/डिलीट करने के बजाय

किसी कथन से प्रभावित प्रत्येक पंक्ति के लिए या एक बार दृढ़ता के लिए फ़ंक्शन को लागू किया जा सकता है। और और भी चीजें हैं, जैसे ट्रिगर्स का कैस्केडिंग, जो सभी को यहां समझाया गया है।

ट्रिगर फ़ंक्शन C में या किसी PL फ़ंक्शन में लिखे जा सकते हैं, लेकिन SQL में नहीं। ऑडिट . में एक पंक्ति सम्मिलित करने के लिए यहां एक उदाहरण दिया गया है तालिका, कीमत . में किए गए प्रत्येक अपडेट के लिए किसी आइटम . का ।

-- first create the function
CREATE FUNCTION log_update() RETURNS TRIGGER AS $$
    INSERT INTO audit (event, new_price, at, item)
      VALUES ('price changed', NEW.price, now(), OLD.item);
$$
LANGUAGE plpgsql;

-- then create the trigger
CREATE TRIGGER audit_price_changes
    AFTER UPDATE ON items
    FOR EACH ROW
    WHEN (OLD.price IS DISTINCT FROM NEW.price)
    EXECUTE FUNCTION log_update();

यहां ट्रिगर के बारे में सभी पढ़ें, साथ ही ट्रिगर दस्तावेज़ बनाएं।

ईवेंट ट्रिगर

जबकि ट्रिगर एक ही टेबल पर DML इवेंट का जवाब दें, इवेंट ट्रिगर किसी विशेष डेटाबेस पर डीडीएल घटनाओं का जवाब दे सकता है। इवेंट में टेबल, इंडेक्स, स्कीमा, व्यू, फंक्शन, टाइप, ऑपरेटर आदि जैसे कई तरह के ऑब्जेक्ट बनाना, बदलना, छोड़ना शामिल है।

यहां एक घटना ट्रिगर है जो 'ऑडिट' स्कीमा से वस्तुओं को छोड़ने से रोकता है:

-- create function first
CREATE FUNCTION nodrop() RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
    IF EXISTS(
      SELECT 1
      FROM pg_event_trigger_dropped_objects() AS T
      WHERE T.schema_name = 'audit')
    THEN
      RAISE EXCEPTION 'not allowed to drop objects in audit schema';
    END IF;
END $$;

-- create event trigger
CREATE EVENT TRIGGER trigger_nodrop
    ON sql_drop
    EXECUTE FUNCTION nodrop();

अधिक जानकारी यहां और CREATE EVENT TRIGGERदस्तावेज़ीकरण में मिल सकती है।

नियम

PostgreSQL एक ऐसी सुविधा के साथ आता है जो आपको क्वेरी प्लानर के लिए रास्ता बनाने से पहले प्रश्नों को फिर से लिखने देता है। यह ऑपरेशन कुछ हद तक एक आने वाले URL को संसाधित करने से पहले उसे फिर से लिखने के लिए Nginx या Apache को कॉन्फ़िगर करने के समान है।

यहां दो उदाहरण दिए गए हैं जो किसी तालिका पर INSERT कथनों को प्रभावित करते हैं और उन्हें कुछ और करने योग्य बनाते हैं:

-- make inserts into "items" table a no-op
CREATE RULE rule1 AS ON INSERT TO items DO INSTEAD NOTHING;

-- make inserts go elsewhere
CREATE RULE rule2 AS ON INSERT TO items DO INSTEAD
    INSERT INTO items_pending_review VALUES (NEW.name, NEW.price);

दस्तावेज़ीकरण के इस अध्याय में नियमों के बारे में अधिक जानकारी है।

संग्रहीत कार्यविधियाँ

Postgres 11 से शुरू करके, संग्रहित प्रक्रियाओं . बनाना संभव है भी। संग्रहीत कार्यों की तुलना में, केवल एक अतिरिक्त चीज है जो प्रक्रियाएं कर सकती हैं - लेनदेन नियंत्रण।

यहां एक उदाहरण दिया गया है:

CREATE PROCEDURE check_commit(v integer)
LANGUAGE plpgsql AS $$
BEGIN
    IF v % 2 = 0 THEN
        COMMIT;
    ELSE
        ROLLBACK;
    END IF;
END $$;

-- call it
CALL check_commit(10);

अधिक जानकारी के लिए यहां और यहां देखें।

अन्य विदेशी चीज़ें

विदेशी डेटा रैपर

फॉरेन डेटा रैपर्स (FDWs) आपको डेटा के अन्य स्रोतों से बात करने देता है, जैसे अन्य पोस्टग्रेज सर्वर, MySQL, Oracle, Cassandra और बहुत कुछ। विदेशी सर्वर तक पहुँचने के लिए सभी तर्क C में एक साझा पुस्तकालय के रूप में लिखे गए हैं।

यहां तक ​​कि FDW पर आधारित cstore_fdw नाम का एक कॉलमर स्टोर भी है।

आप पोस्टग्रेज विकी में FDW कार्यान्वयन की सूची और अधिक दस्तावेज़ीकरण यहाँ पा सकते हैं।

इंडेक्स एक्सेस मेथड्स

PostgreSQL बी-ट्री, हैश, जीआईएन और अधिक जैसे इंडेक्स प्रकारों के साथ आता है। सी साझा पुस्तकालय के रूप में अपने स्वयं के इंडेक्स प्रकार को इसी तरह लिखना संभव है। यहां अधिक विवरण।

टेबल एक्सेस मेथड्स

आगामी PostgreSQL 12 के साथ, अपनी स्वयं की डेटास्टोरेज संरचना बनाना संभव होगा। यहां वर्णित इंटरफ़ेस को लागू करके, आप अपने पसंद के तरीके से टुपल डेटा को भौतिक रूप से डिस्क पर संग्रहीत कर सकते हैं।

तार्किक प्रतिकृति प्लगइन्स

PostgreSQL में, तार्किक प्रतिकृति को "डीकोडिंग" द्वारा राइट-फॉरवर्ड लॉग (WAL) की सामग्री को एक मनमाना प्रारूप (जैसे SQL टेक्स्ट या json) में लागू किया जाता है और प्रतिकृति स्लॉट पर ग्राहकों को प्रकाशित किया जाता है। यह डिकोडिंगलॉजिकल डिकोडिंग आउटपुट प्लगइन . के माध्यम से किया जाता है , जिसे यहां वर्णित सी साझा पुस्तकालय के रूप में कार्यान्वित किया जा सकता है। "test_decoding" साझा पुस्तकालय एक ऐसा प्लगइन है, और आप अपना खुद का निर्माण कर सकते हैं।

प्रक्रियात्मक भाषा हैंडलर

आप अपनी पसंदीदा प्रोग्रामिंग भाषा के लिए एक पोस्टग्रेज पीएल के रूप में एक हैंडलर बनाकर - फिर से एक सी साझा पुस्तकालय के रूप में समर्थन जोड़ सकते हैं। PL/Go या PL/Rust बनाने के लिए यहां से शुरुआत करें!

एक्सटेंशन

एक्सटेंशन पैकेज प्रबंधन का पोस्टग्रेज तरीका है। मान लें कि आपके पास एक सी फ़ंक्शन है जो कुछ उपयोगी करता है, और कुछ SQL कथन जो इसे सेट करने के लिए आवश्यक "फ़ंक्शन बनाएं" कथन बनाते हैं। आप इन आसन "एक्सटेंशन" को बंडल कर सकते हैं जिसे पोस्टग्रेज एक ही चरण में ("क्रिएट एक्सटेंशन" कहकर) इंस्टॉल (और अनइंस्टॉल) कर सकता है। जब आप एक नया संस्करण डालते हैं, तो आप एक्सटेंशन में अपग्रेड चरण भी शामिल कर सकते हैं।

जबकि सर्वर-साइड प्रोग्रामिंग प्रति-से नहीं, एक्सटेंशन आपके सर्वर-साइड कोड को पैकेज और वितरित करने का मानक और बहुत कुशल तरीका है।

एक्सटेंशन के बारे में अधिक जानकारी यहां और यहां पाई जा सकती है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres से SQL Server 2008 में माइग्रेट करना

  2. PostgreSQL में प्रति समूह पहली पंक्ति कैसे प्राप्त करें

  3. SQL में मिलान एल्गोरिथ्म

  4. दूसरी तालिका में संख्या के आधार पर एक तालिका में एकाधिक पंक्तियाँ सम्मिलित करें

  5. एसक्यूएल चयन गति int बनाम varchar