سؤال

أنا جديدة مع كيو و أنا بالفعل أول مشكلة..

كتبت بعض التعليمات البرمجية أن نفهم كيف المعاملات ، دليل خطوة بخطوة.

لجعلها قصيرة, لقد خلق 2 الجداول المستخدم و الحركات:في أول واحد هناك اسم, البريد الإلكتروني و الائتمان الأعمدة في الثانية الأعمدة من, إلى, الاستيراد.

لذا كنت أحاول بهذه الطريقة:

BEGIN;
INSERT INTO movements (from, to, import) VALUES ('mary', 'steve', 600);
UPDATE users SET credit = credit - 600 WHERE name = 'mary';
UPDATE users SET credit = credit + 600 WHERE name = 'steve';
--here comes the problem!
IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
 ROLLBACK;
END IF
COMMIT;

أنا دائما الحصول على الخطأ:

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

أين أنا على خطأ ؟

P. S.:لا تركز على سبيل المثال وظيفة, انها مجرد المحاكمة بالنسبة لي لفهم المعاملات..و الآن إذا شرط...

هل كانت مفيدة؟

المحلول

كما يوهانس بالفعل يقول:كنت خلط العادية SQL مع PL/pgSQL, الإجراء المخزن اللغة.الرابط الذي يوهانس أن شرح مفهوم الإجراءات المخزنة لك.

أنا أعتبر أنك تفعل هذا السيناريو ؟ تنفيذ بيان واحد بعد آخر ؟ أخشى أنك يمكن أن تفعل ما تريد القيام به داخل إجراء مخزن أو دالة ، كما قد نسميها.هذا لأنه عندما يتم تنفيذ البيانات بهذه الطريقة, كل بيان تقف بمفردها لا علاقة أو معلومات بشأن البيانات الأخرى.

وعلاوة على ذلك يمكنك إلقاء نظرة على الرابط التالي لمزيد من المعلومات حول كيفية استخدام إذا ...ثم ...آخر ...END IF;الشرطية داخل plpgsql: الرابط.


تحرير:

أنا لا أعرف إذا كان التراجع هو مسموح به في هذه النقطة (لأن كل الإجراءات المخزنة بالفعل في المعاملة) ، ولكن يجب أن تكون قادرة على معرفة ذلك بنفسك باستخدام وثائق واسعة النطاق @ http://www.postgresql.org.هنا عينة وظيفة مع التعليمات البرمجية الخاصة بك في هذا أيضا مما يدل على بعض بناء الجملة:

CREATE OR REPLACE FUNCTION public.test()
RETURNS integer AS
$$
DECLARE
tempvar integer;

BEGIN    
     tempvar := 1;

     INSERT INTO movements (from, to, import) VALUES ('mary', 'steve', 600);
     UPDATE users SET credit = credit - 600 WHERE name = 'mary';
     UPDATE users SET credit = credit + 600 WHERE name = 'steve';

     --here comes the problem!
     IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
        ROLLBACK;
     END IF;

     RETURN tempvar;
END
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;

ومع ذلك ، إذا كنت حقا تسير في هذا الطريق ، أوصي باستخدام واجهة المستخدم الرسومية DB مدير.من الأسهل تعلم كل هذا.

نصائح أخرى

ويبدو أنك تستخدم SQL سهل لكن البيان IF هو جزء من PL/pgSQL اللغة الإجرائية التي هي جزء من كيو.

هل يمكن أن محاولة تعديل جزء IF، من:

IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
 ROLLBACK;
END IF

إلى

SELECT SUM(credit) INTO v_credit FROM users WHERE name = 'mary';
IF (v_credit) < 0 THEN
 ROLLBACK;
END IF

وعلى افتراض v_credit هو المتغير الذي المحددة سابقا. IMHO، Postgre يفترض الاستعلام SELECT بإرجاع أكثر من نتيجة واحدة، حتى ولو كنت متأكدا جدا أنها فريدة من نوعها. لهذا أعتقد أننا يمكن أن محاولة تعيين القيمة إلى مسبقا الأول متغير.

إذا كنت تريد تجنب إذا كنت قد كتابة التعليمات البرمجية الخاصة بك على النحو التالي:

BEGIN;

    INSERT INTO movements (from, to, import)    
    SELECT 'mary', 'steve', CASE credit < 600 WHEN TRUE THEN 0 ELSE 600 END;

    UPDATE users SET credit = credit - CASE credit < 600 WHEN TRUE THEN 0 ELSE 600 END    
    WHERE name = 'mary';

    UPDATE users u SET u.credit = u.credit + CASE v.credit < 600 WHEN TRUE THEN 0 ELSE 600 END    
    FROM users v    
    WHERE u.name = 'steve' and v.name = 'mary'

COMMIT;

نعم، هذا هو :) غبي.

وعلى غرار SQL مايكروسوفت وT / SQL، يجب أن تكون قادرة على خلط SQL منتظم مع PL / pgSQL إذا كانوا في التسلسل الصحيح. وإليك مثال حيث مسائل التسلسل في SQL مختلط / إجراءات PL المخزنة:

وأنت لا يمكن التفاف العبارات الشرطية داخل المؤشر - يجب وضع المؤشر داخل عبارة شرطية. إذا قمت بذلك تسلسل على العكس من ذلك، سوف تحصل على نفس الخطأ كما كنت رأيت، 'خطأ: خطأ في بناء الجملة عند أو بالقرب من "IF"':

CREATE OR REPLACE FUNCTION getSubsystemFaultListCount(_bunoid integer, _subsystem text, _starttime timestamp without time zone, _stoptime timestamp without time zone)
      RETURNS refcursor AS
    $BODY$
    DECLARE mycurs refcursor;
    BEGIN 
        IF _subsystem = 'ALL' THEN
            OPEN mycurs FOR
            SELECT  count(*), fs_fault.faultcode, fs_fault.downloadtime
            FROM    fs_fault
            WHERE   fs_fault.bunoid = _bunoid
                AND fs_fault.statusid IN(2, 4)
                AND fs_fault.downloadtime BETWEEN _starttime AND _stoptime
            GROUP BY fs_fault.faultcode, fs_fault.downloadtime;
            RETURN mycurs;
        ELSE
            OPEN mycurs FOR
            SELECT  count(*), fs_fault.faultcode, fs_fault.downloadtime
            FROM    fs_fault
            WHERE   fs_fault.bunoid = _bunoid
                AND fs_fault.subsystemid 
                    IN(SELECT id FROM fs_subsystem WHERE type = _subsystem)
                AND fs_fault.statusid IN(2, 4)
                AND fs_fault.downloadtime BETWEEN _starttime AND _stoptime
            GROUP BY fs_fault.faultcode, fs_fault.downloadtime;
            RETURN mycurs;
        END IF;

    END;
    $BODY$

وأنا مبتدئ في PostGresSQL. هذه هي وظيفة مجرد مثال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top