आपके पोस्ट किए गए उत्तर का सरल विकल्प। बहुत बेहतर प्रदर्शन करना चाहिए।
यह फ़ंक्शन किसी दी गई तालिका से एक पंक्ति पुनर्प्राप्त करता है (in_table_name
) और प्राथमिक कुंजी मान (in_row_pk
), और इसे उसी तालिका में नई पंक्ति के रूप में सम्मिलित करता है, कुछ मानों को बदल दिया जाता है (in_override_values
) डिफ़ॉल्ट रूप से नया प्राथमिक कुंजी मान लौटाया जाता है (pk_new
)।
CREATE OR REPLACE FUNCTION f_clone_row(in_table_name regclass
, in_row_pk int
, in_override_values hstore
, OUT pk_new int) AS
$func$
DECLARE
_pk text; -- name of PK column
_cols text; -- list of names of other columns
BEGIN
-- Get name of PK column
SELECT INTO _pk a.attname
FROM pg_catalog.pg_index i
JOIN pg_catalog.pg_attribute a ON a.attrelid = i.indrelid
AND a.attnum = i.indkey[0] -- 1 PK col!
WHERE i.indrelid = 't'::regclass
AND i.indisprimary;
-- Get list of columns excluding PK column
_cols := array_to_string(ARRAY(
SELECT quote_ident(attname)
FROM pg_catalog.pg_attribute
WHERE attrelid = in_table_name -- regclass used as OID
AND attnum > 0 -- exclude system columns
AND attisdropped = FALSE -- exclude dropped columns
AND attname <> _pk -- exclude PK column
), ',');
-- INSERT cloned row with override values, returning new PK
EXECUTE format('
INSERT INTO %1$I (%2$s)
SELECT %2$s
FROM (SELECT (t #= $1).* FROM %1$I t WHERE %3$I = $2) x
RETURNING %3$I'
, in_table_name, _cols, _pk)
USING in_override_values, in_row_pk -- use override values directly
INTO pk_new; -- return new pk directly
END
$func$ LANGUAGE plpgsql;
कॉल करें:
SELECT f_clone_row('t', 1, '"col1"=>"foo_new","col2"=>"bar_new"'::hstore);
-
regclass
का इस्तेमाल करें इनपुट पैरामीटर प्रकार के रूप में, इसलिए शुरू करने के लिए केवल मान्य तालिका नामों का उपयोग किया जा सकता है और SQL इंजेक्शन को खारिज कर दिया जाता है। यदि आपको एक अवैध तालिका नाम प्रदान करना चाहिए, तो फ़ंक्शन पहले और अधिक शानदार ढंग से विफल हो जाता है। -
एक
आउट
का प्रयोग करें पैरामीटर (pk_new
) वाक्य रचना को सरल बनाने के लिए। -
प्राथमिक कुंजी के लिए मैन्युअल रूप से अगला मान निकालने की आवश्यकता नहीं है। यह स्वचालित रूप से डाला जाता है और तथ्य के बाद वापस आ जाता है। यह न केवल सरल और तेज़ है, आप व्यर्थ या आउट-ऑफ-ऑर्डर अनुक्रम संख्याओं से भी बचते हैं।
-
format()का उपयोग करें कोड>
गतिशील क्वेरी स्ट्रिंग की असेंबली को सरल बनाने और इसे कम त्रुटि-प्रवण बनाने के लिए। ध्यान दें कि मैं क्रमशः पहचानकर्ताओं और स्ट्रिंग्स के लिए स्थितीय मापदंडों का उपयोग कैसे करता हूं। -
मैं आपकी अंतर्निहित धारणा . पर आधारित हूं अनुमति दी गई तालिकाओं में एक एक डिफ़ॉल्ट स्तंभ के साथ पूर्णांक प्रकार का एकल प्राथमिक कुंजी स्तंभ होता है . आमतौर पर
serial
कॉलम। -
फ़ंक्शन का मुख्य तत्व अंतिम है
INSERT
:#=
ऑपरेटर उप-चयन में और परिणामी पंक्ति को तुरंत विघटित करें।- तब आप मुख्य
SELECT
. में केवल प्रासंगिक कॉलम चुन सकते हैं । - Postgres को PK के लिए डिफ़ॉल्ट मान निर्दिष्ट करने दें और इसे
रिटर्निंग
के साथ वापस प्राप्त करें खंड। - लौटा हुआ मान
OUT
में लिखें सीधे पैरामीटर। - सब कुछ एक SQL कमांड में किया जाता है, जो आमतौर पर सबसे तेज़ होता है।