it-swarm.asia

Postgres plpgsql - استخدام متغير داخل عبارة إنشاء ديناميكية

باستخدام Postgres pl/pgsql ، أحاول إنشاء جدول باستخدام أمر EXECUTE ديناميكي ، مثل:

 ...
 DECLARE
    tblVar varchar := "myTable";
 BEGIN
 EXECUTE 'CREATE TABLE $1 ( 
             foo integer NOT NULL, 
             bar varchar NOT NULL)'
 USING _tblVar;
 ...

ومع ذلك ، ما زلت أتلقى رسالة الخطأ

خطأ: خطأ في بناء الجملة أو بالقرب من "$ 1"

إذا لم أستخدم $1 الرمز المميز ، وبدلاً من ذلك ، اكتب السلسلة myTable تعمل بشكل جيد.

هل هناك قيود على استخدام عبارات ديناميكية لمكالمات CREATE؟

8
Jmoney38

بالإضافة إلى ما كتبهfiliprem ، إليك كيفية القيام بذلك بشكل صحيح:

...
DECLARE
   tbl_var text := 'myTable';   -- I would not use mixed case names ..
BEGIN
EXECUTE '
CREATE TABLE ' || quote_ident(tbl_var) || '( 
   foo integer NOT NULL, 
   bar text NOT NULL)';
...

استخدم quote_ident() لتجنب إدخال SQL أو أخطاء في بناء الجملة. سيقتبس الأسماء ذات الأحرف غير القياسية أو الكلمات المحجوزة.

قمت أيضًا باستبدال علامات الاقتباس المزدوجة التي كانت لديك حول قيمة السلسلة في مثالك علامات اقتباس مفردة .

5
Erwin Brandstetter

انظر http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

لاحظ أنه لا يمكن استخدام رموز المعلمات إلا لقيم البيانات - إذا كنت ترغب في استخدام أسماء الجداول أو الأعمدة المحددة ديناميكيًا ، يجب عليك إدراجها في سلسلة الأوامر بشكل نصي. على سبيل المثال ، إذا احتاج الاستعلام السابق إلى جدول محدد ديناميكيًا ، فيمكنك القيام بذلك:

EXECUTE 'SELECT count(*) FROM '
    || tabname::regclass
    || ' WHERE inserted_by = $1 AND inserted <= $2'
   INTO c
   USING checked_user, checked_date;

كما هو موضح في التعليقات أدناه ، فإن طريقة الإرسال ليست مجدية دائمًا ، خاصةً لبيانات CREATE. ضع في الاعتبار وظيفة format ، على سبيل المثال:

EXECUTE format(
  'CREATE TABLE %I (%I %I, %I %I)',
  v_tabname,
  v_col1name, v_col1type,
  v_col2name, v_col2type);

بعبارات أخرى:

نعم ، هناك مثل هذا القيد. لا يمكنك استخدام معلمات لأسماء الجدول/العمود - وذلك لأن Postgresql يحتاج إلى أن يكون قادرًا على تحليل الاستعلام عند تجميع جملة SQL الديناميكية. يجب أن يكون المحلل قادرًا على تحديد العلاقات المستخدمة.

ملاحظة جانبية: ربما ينطبق هذا القيد على SQL الديناميكي في DBMS أخرى ، بما في ذلك Oracle: http://download.Oracle.com/docs/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDHGHIF =

3
filiprem