используя функцию rownum в pl sql - PullRequest
0 голосов
/ 14 апреля 2020

Привет всем, пожалуйста, я новичок в pl sql и запутался в функции ROWNUM. На самом деле у меня есть pl sql код, который использует 2 таблицы EMPLOYEE и WORKS_ON, и мы создаем ассоциативный массив, а затем сохраняем первую запись, а вторую я помещаю и код, и результаты, и таблицы. мой вопрос, почему мы ставим rownum <= 1, чтобы получить вторую запись, и когда я использую rownum <= 2, это дает ошибку: <a href="https://imgur.com/9DPJmHo" rel="nofollow noreferrer"> это изображение таблиц и вывод

SET SERVEROUTPUT ON;

DECLARE

 --Declare the table
 TYPE EmpSSNarray
 IS TABLE OF employee.ssn%TYPE
 INDEX BY SIMPLE_INTEGER;

 --Declare variables using the table
 ManagementList  EmpSSNarray;
 WorkerList      EmpSSNarray;

BEGIN

 --Retrieve the first Supervisor
 SELECT superssn
 INTO ManagementList(1)
 FROM employee
 WHERE superssn IS NOT NULL
 AND ROWNUM <= 1;

 --Retrieve the second Supervisor
 SELECT superssn
 INTO ManagementList(2)
 FROM employee
 WHERE superssn IS NOT NULL
 AND ROWNUM <= 1
 AND superssn <> ManagementList(1);

 --Retrieve the first worker
 SELECT essn
 INTO WorkerList(1)
 FROM works_on
 WHERE hours IS NOT NULL
 AND ROWNUM <= 1
 AND essn NOT IN (ManagementList(1), ManagementList(2));

 --Retrieve the second worker
 SELECT essn
 INTO WorkerList(2)
 FROM works_on
 WHERE hours IS NOT NULL
 AND ROWNUM <= 1
 AND essn NOT IN (ManagementList(1), ManagementList(2),WorkerList(1));

 --Output the results
 dbms_output.put_line ('Managers are: ' || ManagementList(1) || ', ' || ManagementList(2));
 dbms_output.put_line ('Workers are: ' || WorkerList(1) || ', ' || WorkerList(2));


END;

Ответы [ 3 ]

1 голос
/ 14 апреля 2020

Используйте коллекцию вместо ассоциативного массива PL / SQL:

CREATE TYPE EmpSSNarray IS TABLE OF NUMBER(8,0);

Затем вы можете использовать BULK COLLECT INTO для хранения нескольких строк в коллекции и, если вы определили ее в глобальная SQL область видимости, а не локальный тип PL / SQL, тогда вы также можете использовать оператор MEMBER OF:

DECLARE
  ManagementList  EmpSSNarray;
  WorkerList      EmpSSNarray;
BEGIN
  SELECT superssn
  BULK COLLECT INTO ManagementList
  FROM   employee
  WHERE  superssn IS NOT NULL
  AND    ROWNUM <= 2;

  SELECT essn
  BULK COLLECT INTO WorkerList
  FROM   works_on
  WHERE  hours IS NOT NULL
  AND    ROWNUM <= 2
  AND    essn NOT MEMBER OF management_list;

 --Output the results
 dbms_output.put_line ('Managers are: ' || ManagementList(1) || ', ' || ManagementList(2));
 dbms_output.put_line ('Workers are: ' || WorkerList(1) || ', ' || WorkerList(2));
END;
/

Итак, если ваши таблицы:

CREATE TABLE employee ( ssn, superssn ) AS
SELECT 1, 3    FROM DUAL UNION ALL
SELECT 2, 4    FROM DUAL UNION ALL
SELECT 3, 5    FROM DUAL UNION ALL
SELECT 4, 5    FROM DUAL UNION ALL
SELECT 5, NULL FROM DUAL;

CREATE TABLE works_on ( essn, hours ) AS
SELECT 1, 10 FROM DUAL UNION ALL
SELECT 5, 20 FROM DUAL UNION ALL
SELECT 2, 30 FROM DUAL;

Тогда PL / SQL выдаст:

Managers are: 4, 3
Workers are: 5, 1

дБ <> скрипка здесь

0 голосов
/ 14 апреля 2020

Если вы хотите получить вторую запись, вы можете использовать что-то вроде ниже

SELECT superssn
    INTO   Managementlist(2)
    FROM   (SELECT superssn,
                   ROWNUM rw,
                    ssn
            FROM   employee
            WHERE  superssn IS NOT NULL
                   order by ssn)
    WHERE  rw = 2; 
0 голосов
/ 14 апреля 2020

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

rownum - порядковый номер, назначенный записям в наборе результатов, указывающий порядок, в котором они возвращаются из базы данных. Если n - размер результирующего набора, записи нумеруются непрерывно с 1..n.

Предложение rownum <= 1 в условиях where, таким образом, является обобщенным c средством для уменьшения числа записей в результирующем наборе равным 1. Очевидно, что предложение rownum <= [any number k > 1] в общем случае создаст k записей, вызывающих ошибку.

Представленные запросы могут по-прежнему терпеть неудачу, если запросы (без предложения rownum ) даст пустой набор результатов. Вероятно, что бизнес-логика c исключает эту возможность (например, гарантируется [и обеспечивается ограничениями или триггерами], что таблица employee всегда содержит как минимум 2 супервизора).

На первый взгляд может показаться бессмысленным ограничивать результирующий набор «первой записью» без сортировки. Однако, если интерес представляет только какая-то запись, удовлетворяющая другим условиям в предложении where (или вообще никаких условий), конструкция может быть разумной, поскольку она позволяет избежать потенциально дорогой сортировки.

...