Совместное использование SQL и Perl - что следует использовать для общих функций? - PullRequest
4 голосов
/ 20 декабря 2010

Я не нашел дубликатов этого вопроса, но если есть один или несколько, извините - пожалуйста, прокомментируйте со ссылкой.

Вопрос является основным, как, вероятно, ответ. Если я использую Perl для выполнения и работы с базой данных, на какой путь (Perl против SQL) я должен возложить бремя, когда задействованы общие функции?

Такие функции, как - LEN, IF/ELSE, CONCAT и многие другие, а также арифметические функции, например, являются общими для обеих систем.

Этот оператор SQL загружается с блоками case и другими операциями, которые можно реплицировать с помощью Perl. Итак, если та же логика может быть реализована в Perl, стоит ли переписывать? Какие условия влияют на решение взять на себя бремя одной системы и переложить ее на другую?

SELECT DISTINCT     s.id stu_id,
                    stu_id.fullname stu_name,
                    p.major1 major,
                    p.minor1 minor,
                    s.reg_hrs,
                    NVL(st.cum_earn_hrs,0) ttl_hrs,
                    p.adv_id curr_adv_id,
                    adv_id.fullname curr_adv_name,
                    CASE    WHEN    (p.adv_id <> 35808 AND p.major1 = 'NS')                 THEN    (1165)
                            WHEN    (p.adv_id = 35808 AND p.major1 = 'NS')                  THEN    (35808)
                            WHEN    (p.adv_id = 9179 AND p.major1 = 'DART')                 THEN    (9179)
                            WHEN    (p.minor1 IN ('RT','RESP') AND st.cum_earn_hrs >= 24)   THEN    (70897)
                            WHEN    (p.major1 IN ('CDSC','CDSD'))                           THEN    (52125)
                            WHEN    (p.major1 IN ('CA','CB'))                               THEN    (24702)
                            WHEN    (p.minor1 = 'NURS')                                     THEN    (51569)
                            WHEN    (p.major1 = 'LEG')                                      THEN    (13324)
                            WHEN    (p.major1 = 'CC')                                       THEN    (73837)
                            WHEN    (p.major1 = 'CCRE')                                     THEN    (1133)
                            WHEN    ((p.adv_id IN (SELECT DISTINCT id FROM fac_rec WHERE stat = 'I'))
                                    OR (st.cum_earn_hrs < 24 AND (p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0 AND min_hrs >= 24))
                                    OR (s.id NOT IN (SELECT DISTINCT stu.id FROM stu_acad_rec stu, sess_info si WHERE stu.yr = si.prev_yr AND stu.sess = si.prev_sess AND stu.reg_hrs > 0 AND stu.reg_stat IN ('C','R') AND stu.prog = 'UNDG'))
                                    OR ((p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat <> 'A' OR max_stu <= 0))
                                    OR ((p.adv_id||p.major1) NOT IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0)))
                            THEN    (9238)
                            ELSE    (p.adv_id)
                    END     new_adv_id,
                    CASE    WHEN    (p.adv_id <> 35808 AND p.major1 = 'NS')                 THEN    ('Deborah')
                            WHEN    (p.adv_id = 35808 AND p.major1 = 'NS')                  THEN    ('Veronica')
                            WHEN    (p.adv_id = 9179 AND p.major1 = 'DART')                 THEN    ('Stella')
                            WHEN    (p.minor1 IN ('RT','RESP') AND st.cum_earn_hrs >= 24)   THEN    ('Lisa')
                            WHEN    (p.major1 IN ('CDSC','CDSD'))                           THEN    ('Joanne')
                            WHEN    (p.major1 IN ('CA','CB'))                               THEN    ('Barbara')
                            WHEN    (p.minor1 = 'NURS')                                     THEN    ('Karen')
                            WHEN    (p.major1 = 'LEG')                                      THEN    ('Nancy')
                            WHEN    (p.major1 = 'CC')                                       THEN    ('Alberta')
                            WHEN    (p.major1 = 'CCRE')                                     THEN    ('Naomi')
                            WHEN    ((p.adv_id IN (SELECT DISTINCT id FROM fac_rec WHERE stat = 'I'))
                                    OR (st.cum_earn_hrs < 24 AND (p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0 AND min_hrs >= 24))
                                    OR (s.id NOT IN (SELECT DISTINCT stu.id FROM stu_acad_rec stu, sess_info si WHERE stu.yr = si.prev_yr AND stu.sess = si.prev_sess AND stu.reg_hrs > 0 AND stu.reg_stat IN ('C','R') AND stu.prog = 'UNDG'))
                                    OR ((p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat <> 'A' OR max_stu <= 0))
                                    OR ((p.adv_id||p.major1) NOT IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0)))
                            THEN    ('Staff')
                            ELSE    (adv_id.fullname)
                    END     new_adv_name,
                    CASE    WHEN    (p.adv_id <> 35808 AND p.major1 = 'NS')                 THEN    ('NS majors not assigned to Veronica go to Debbie')
                            WHEN    (p.adv_id = 35808 AND p.major1 = 'NS')                  THEN    ('NS majors stay with Veronica')
                            WHEN    (p.adv_id = 9179 AND p.major1 = 'DART')                 THEN    ('DART majors stay with Stella')
                            WHEN    (p.minor1 IN ('RT','RESP') AND st.cum_earn_hrs >= 24)   THEN    ('RT-RESP minors go to Lisa')
                            WHEN    (p.major1 IN ('CDSC','CDSD'))                           THEN    ('CDSC-CDSD majors go to Joanne')
                            WHEN    (p.major1 IN ('CA','CB'))                               THEN    ('CA-CB majors go to Barbara')
                            WHEN    (p.minor1 = 'NURS')                                     THEN    ('NURS minors go to Karen')
                            WHEN    (p.major1 = 'LEG')                                      THEN    ('LEG majors go to Nancy')
                            WHEN    (p.major1 = 'CC')                                       THEN    ('CC majors go to Alberta')
                            WHEN    (p.major1 = 'CCRE')                                     THEN    ('CCRE majors go to Naomi')
                            WHEN    (p.adv_id IN (SELECT DISTINCT id FROM fac_rec WHERE stat = 'I'))
                            THEN    ('Current advisor is inactive')
                            WHEN    (st.cum_earn_hrs < 24 AND (p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0 AND min_hrs >= 24))
                            THEN    ('Total credits for this student did not meet the advisor reqs for this major')
                            WHEN    (s.id NOT IN (SELECT DISTINCT stu.id FROM stu_acad_rec stu, sess_info si WHERE stu.yr = si.prev_yr AND stu.sess = si.prev_sess AND stu.reg_hrs > 0 AND stu.reg_stat IN ('C','R') AND stu.prog = 'UNDG'))
                            THEN    ('This student did not attend '||si.prev_sess||si.prev_yr)
                            WHEN    ((p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE (stat <> 'A' OR max_stu <= 0)))
                            THEN    ('Current advisor is not advising students with this major')
                            WHEN    ((p.adv_id||p.major1) NOT IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0))
                            THEN    ('Current advisor is not advising students with this major')
                            ELSE    ('Student will stay with current advisor')
                    END     change_comm
FROM                stu_acad_rec s,
                    prog_enr_rec p,
                    OUTER stu_stat_rec st,
                    id_rec stu_id,
                    id_rec adv_id,
                    sess_info si
WHERE               s.id = p.id
                    AND s.id = st.id
                    AND s.id = stu_id.id
                    AND p.adv_id = adv_id.id
                    AND s.yr = si.curr_yr
                    AND s.sess = si.curr_sess
                    AND s.reg_hrs > 0
                    AND s.reg_stat IN ('C','R')
                    AND s.prog = 'UNDG'
                    AND p.prog = 'UNDG'
                    AND st.prog = 'UNDG'
                    AND s.id NOT IN (3,287,9238,59999) {System test use IDs}
INTO TEMP           stu_list
WITH NO LOG;

Ответы [ 3 ]

4 голосов
/ 20 декабря 2010

Я бы посмотрел на это с точки зрения производительности и с точки зрения повторного использования.

Если вы попробуете это с обеих сторон, вы можете обнаружить, что один из них намного быстрее другого - это будет хорошим показателем для выбора.

Если вы будете повторно использовать какой-либо запрос более чем в одном месте, то вы захотите включить большую часть бизнес-логики в запрос, насколько это возможно, поэтому вам не нужно повторять это в графическом интерфейсе.

(и я должен сказать, хотя это не является частью вашего вопроса, что большая часть логики этого случая выглядит так, как будто вы могли бы сделать хорошую схему в схеме и заменить случай обычным соединением с некоторыми ассоциативными таблицами)

3 голосов
/ 20 декабря 2010

Здесь есть 2 соображения:

  1. Производительность и масштабируемость:

    Если у вас есть только несколько (1-2) одновременно работающих клиентов, SQL может быстрее выполнить ту же логику.

    Однако, если вы начнете увеличивать масштабирование, гораздо БОЛЬШЕ сложнее масштабировать веб-сервер, чем добавлять новых клиентов (или серверы приложений, если ваша бизнес-логика находится на сервере приложений). Таким образом, для любого значительного масштаба запросов ВСЕГДА следует пытаться разгрузить как можно больше обработки с сервера SQL.

  2. Повторное использование кода:

    • Если у вас есть только ОДИН фрагмент кода Perl, который будет выполнять эту логику, то вы также можете поместить его в SQL или Perl.

    • Если у вас> 1 кусок кода Perl, который выполняет эту логику, вы можете либо поместить его в SQL (но см. Компромисс производительности, рассмотренный выше), либо, что еще лучше, поместить его в модуль Perl и использовать этот модуль везде. В основном, объект доступа к данным (DAO).

    • Если у вас есть код на МНОГИХ языках, включая Perl, который нуждается в этом, то вам нужно решить для себя, перевешивают ли проблемы с производительностью хранения кода на SQL-сервере больший объем поддержки правильной логики DAO в синхронизации между библиотеками в > 1 язык.

      Очевидно, что если вы используете логику на стороне SQL, вы ДОЛЖНЫ инкапсулировать ее в представление или хранимую процедуру, чтобы избежать дублирования кода в этих нескольких языках.

3 голосов
/ 20 декабря 2010

Простые функции, такие как LEN или SUM или COUNT, обычно лучше всего выполнять на SQL.

Этот список случаев монстров, с другой стороны, я бы, вероятно, оставил в приложении (ииспользуйте словарь, а не множество переключателей)

РЕДАКТИРОВАТЬ - или присоединиться к другой таблице, чтобы исключить многие из этих случаев.хороший ответ Рэнди.когда у вас так много случаев, он доходит до того, что его данные, а не логика, и запрос не должны содержать сами данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...