пятница, декабря 09, 2011

Oracle, как выбрать подмножество строк


Выбрать строки 10..20 из HR.departments

select * 
  from (select d.*, rownum rnum
          from HR.departments d
         where rownum <= 20)
where rnum >= 10

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

select * 
  from (select d.*, rownum rnum
          from HR.departments d
         where rownum <= 20
         order by d.department_name)
where rnum >= 10


но работать будет не правильно - значения rownum определяются на этапе выборки данных и при выполнении order by порядок будет утерян. 

Поэтому в таком случае можно обернуть выборку и сортировку в ещё один select:

select * 
from (
  select data.*, rownum rnum 
  from ( 
    select d.*
    from HR.departments d
    order by d.department_name ) data
  where rownum <= 20 )
where rnum >= 10


четверг, декабря 08, 2011

Cursor и порядок

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

Пусть есть таблица:
CREATE TABLE A( F1 NUMBER(1), F2 FLOAT);

с такими данными:
INSERT INTO A VALUES(1, 11.1);  
INSERT INTO A VALUES(2, 22.22);
INSERT INTO A VALUES(3, 33.333);

И пусть мне захотелось сделать курсор, который бы содержал данные из этой таблицы:
DECLARE
  TYPE a_cursor_type IS REF CURSOR RETURN A%ROWTYPE;
  a_cursor a_cursor_type;
  
  a_record A%ROWTYPE;
BEGIN
  OPEN a_cursor FOR SELECT f1, f2 FROM A;
  
  LOOP
    FETCH a_cursor INTO a_record;
    EXIT WHEN a_cursor%NOTFOUND;
    
    dbms_output.put_line('F1: ' || a_record.f1 || ', F2: ' || a_record.f2);
  END LOOP;
END;

В выражении SELECT f1, f2 FROM A важно не перепутать порядок выбираемых полей таблицы - хотя в обычной жизни на такие вещи не обращаешь внимания. А вот с курсором обращать приходится, в противном случае вместо ожидаемого результата
F1: 1, F2: 11.1
F1: 2, F2: 22.22
F1: 3, F2: 33.333

легко получить
Error report:
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at line 10
06502. 00000 -  "PL/SQL: numeric or value error%s"

При этом повезёт, если типы столбцов или содержащиеся в них значения окажутся не совместимые и сразу получим сообщение об ошибке. Иначе можно совсем долго разбираться, отчего в нужных столбцах показываются неправильные данные.




понедельник, декабря 05, 2011

Как подключиться из ERwin к Oracle

Предположим, я хочу выполнить Reverse Engineer для какой-то схемы базы. Для этого я вызываю Tools -> Reverse Engineer... Появляется диалог, в котором я указываю тип СУБД - Oracle


Нажимаю Next.

Изменяю или оставляю заданные значения опций импорта на появившемся окне:


и снова нажимаю Next.

Появляется окно, в котором нужно указать свойства подключения к базе данных.

Здесь я указываю тип аутентификации - у меня используется Database Authentification.
Указываю значения username и пароля. 

После этого необходимо указать значение строки соединения (connection string). Значение этой строки можно добыть из tnsnames.ora.

В tnsnames.ora выбираю определение

XE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = desktop-1)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE)
    )
  )

Это выражение нужно привести к одной строке, убрав переводы строк, получив вот такое:

(DESCRIPTION =  (ADDRESS = (PROTOCOL = TCP)(HOST = desktop-1)(PORT = 1521)) (CONNECT_DATA =  (SERVER = DEDICATED) (SERVICE_NAME = XE)))

Копирую эту строку в поле ввода Connection String - и можно нажимать Connect. 



воскресенье, декабря 04, 2011

Поле для хранения GUID в Oracle, использование SYS_GUID

Тип данных для хранения значения - RAW(16).
Для автогенерации значения можно сделать триггер, использовать хранимую процедуру, а можно и вот так:

CREATE TABLE TEST(ID RAW(16) DEFAULT SYS_GUID(), ...);

С другой стороны, если хотим получить значение созданного идентификатора, как обычно и бывает, можно вот так

DECLARE guid RAW(16);
BEGIN
  guid := SYS_GUID();
  INSERT INTO TEST2(ID, NAME) VALUES(guid, 'ПЖиВ И медведи');
END;