COUNT в PLSQL ORACLE - PullRequest
       3

COUNT в PLSQL ORACLE

0 голосов
/ 14 октября 2011

Я задавал этот вопрос раньше, но мне не помогли. Я хочу получить количество строк в двух разных таблицах с учетом атрибута. Это мой код Вместо того, чтобы извлекать общее количество, где выполняется условие, я получаю полный счет таблицы

    create or replace PROCEDURE p1( suburb IN varchar2 ) 
    as
        person_count NUMBER;
        property_count NUMBER;
    BEGIN
        SELECT count(*) INTO person_count
        FROM person p WHERE p.suburb = suburb ;

        SELECT count(*) INTO property_count
        FROM property pp WHERE pp.suburb = suburb ;


        dbms_output.put_line('Number of People :'|| person_count);
        dbms_output.put_line('Number of property :'|| property_count);

    END;
    /

Есть ли другой способ сделать это, чтобы я мог получить реальное общее количество людей в этом пригороде

Некоторые данные из ЛИЧНОГО СТОЛА

       PEID FIRSTNAME       LASTNAME
    ---------- -------------------- --------------------
    STREET                   SUBURB           POST TELEPHONE
    ---------------------------------------- -------------------- ---- ------------
        30 Robert       Williams
    1/326 Coogee Bay Rd.             Coogee           2034 9665-0211

        32 Lily         Roy
   66 Alison Rd.                 Randwick         2031 9398-0605

        34 Jack         Hilfgott
    17 Flood St.                 Bondi            2026 9387-0573

НЕКОТОРЫЕ ДАННЫЕ из ТАБЛИЦЫ ИМУЩЕСТВА

          PNO STREET                    SUBURB       POST
    ---------- ---------------------------------------- -------------------- ----
    FIRST_LIS TYPE               PEID
    --------- -------------------- ----------
        48 66 Alison Rd.                Randwick         2031
    12-MAR-11 Commercial            8

        49 1420 Arden St.               Clovelly         2031
    27-JUN-10 Commercial               82

        50 340 Beach St.                Clovelly         2031
    05-MAY-11 Commercial               38

Извините за то, как выглядит стол.

Это значение, которое я получаю при запуске вышеуказанного скрипта.

     SQL> exec p1('Randwick')
     Number of People :50
     Number of property :33

Я изменил ПРОЦЕДУРУ, вот что я получаю.

    SQL> create or replace PROCEDURE p1( location varchar2 ) 
    IS
        person_count NUMBER;
        property_count NUMBER;
    BEGIN
        SELECT count(p.peid) INTO person_count
        FROM person p WHERE p.suburb = location ;

        SELECT count(pp.pno) INTO property_count
        FROM property pp WHERE pp.suburb = location ;


        dbms_output.put_line('Number of People :'|| person_count);
        dbms_output.put_line('Number of property :'|| property_count);

    END;
    /
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17  
    Procedure created.

    SQL> exec p1('KINGSFORD')
    Number of People :0
    Number of property :0

    PL/SQL procedure successfully completed.

    SQL> 


    SQL> 
    SQL> exec p1('Randwick')
    Number of People :0
    Number of property :0

    PL/SQL procedure successfully completed.

    SQL> 

Решение предположить, что это

    SQL> exec p1('randwick');
    Number of People: 7
    Number of Property: 2

Ответы [ 3 ]

7 голосов
/ 14 октября 2011

Вы назвали переменную так же, как поле. В запросе suburb сначала ищется в объеме запроса, и он соответствует полю suburb, даже если он не использует псевдоним таблицы pp.

Таким образом, вы фактически сравниваете поле с самим собой, поэтому получаете все записи (где suburb НЕ НУЛЬ, то есть). Параметр процедуры вообще не используется в запросе.

Решение: изменить имя параметра процедуры.

Чтобы предотвратить подобные ошибки, я всегда использую P_ в качестве префикса для параметров процедуры / функции и V_ в качестве префикса для локальных переменных. Таким образом, они никогда не смешиваются с именами полей.

1 голос
/ 24 мая 2013

Хотя я согласен с тем, что причиной проблемы является проблема пространства имен между SQL и PL / SQL, поскольку механизм SQL «захватил» имя переменной PL / SQL, я не верю, что изменение именипараметра является лучшим подходом.Если вы сделаете это, вы обрекаете каждого разработчика на то, чтобы начинать префикс каждого имени параметра с «p_» или какого-либо другого бесполезного дополнения, и чтобы они никогда не создавали столбец с префиксом P_.

Если вы просматриваетеВ документации по поставляемым пакетам PL / SQL вы встречаете очень мало случаев (если таковые имеются), когда сами Oracle делают это, хотя в прошлом они делали раздражающе противоречивые вещи, такие как именование table_name как «tabname».

Более надежныйподход заключается в том, чтобы префикс имени переменной с именем процедуры pl / sql при обращении к ней в выражениях SQL:

SELECT count(*)
INTO   person_count
FROM   person p WHERE p.suburb = p1.suburb ;

В вашем случае вы явно не назвали бы вашу процедуру "P1", так что на самом деле вы быиметь что-то вроде:

SELECT count(*)
INTO   person_count
FROM   person p WHERE p.suburb = count_suburb_objects.suburb ;

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

0 голосов
/ 24 мая 2013

Сначала создайте индексы для поиска без учета регистра:

CREATE INDEX idx_person_suburb_u ON person(upper(suburb))
/
CREATE INDEX idx_property_suburb_u ON property(upper(suburb))
/

Во-вторых, используйте префиксы для параметров процедуры и локальных переменных:

CREATE OR REPLACE PROCEDURE p1(p_location VARCHAR2) 
IS
    v_person_count    NUMBER;
    v_property_count  NUMBER; 
    v_location        VARCHAR2(32767);
BEGIN
    IF p_location IS NOT NULL THEN
      v_location := upper(p_location);
      SELECT count(*) INTO v_person_count
      FROM person WHERE upper(suburb) = v_location ;

      SELECT count(*) INTO v_property_count
      FROM property WHERE upper(suburb) = v_location ;
    ELSE
      SELECT count(*) INTO v_person_count
      FROM person WHERE upper(suburb) IS NULL;

      SELECT count(*) INTO v_property_count
      FROM property WHERE upper(suburb) IS NULL;        
    END IF;
    dbms_output.put_line('Number of People :' || v_person_count);
    dbms_output.put_line('Number of Property :' || v_property_count);
END;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...