тип TABLE и работа с ним из РНР

romutis

Guest
tony2001
Ок, попытаюсь сказать что-нить содержательное.

Что NESTED TABLE, что VARRAY - оба являются _переменными_ и работа с ними идет именно как с переменными - т.е. присвоение значений, но не DML-операции. Разница между NESTED TABLE и VARRAY лишь в том, что VARRAY имеет ограничение по размеру (размер задается при создании), а NESTED TABLE - полностью динамическая. Соотв. методы .EXTEND, .TRIM, .DELETE не оказывают влияния на объекты типа VARRAY.

Теперь о БД. И те и другие объекты можно хранить в таблицах в виде столбца-указателя на объект. Оба объявляются как столбец объявленного типа:
CREATE OR REPLACE TYPE my_varray as varray(20) of varchar2(2000);
CREATE OR REPLACE TYPE my_table as table of varchar2(2000);
CREATE TABLE TEST (
IND number not null,
column_varray my_varray,
column_table my_table)
NESTED TABLE column_table store as column_table;

Вот здесь будет работать SELECT/INSERT/UPDATE/DELETE для таблицы TEST - но вы не сможете сделать UPDATE/INSERT/DELETE для отдельных элементов столбцов column_varray или column_table в отдельности от. Всё, что можно - это считать все значения этих столбцов куда-нибудь, изменить значения (помним, что это переменная, да?) и записать обратно.

Вот такая скучная матчасть получилась... :)
Я активно пользую оба вида этих COLLECTIONS, но только не для того, чтобы их в базе хранить - ИМХО, изврат. В версии 10g должна быть поулучшена работа с COLLECTIONS - но я "десятку" видел лишь на бета-тестировании, поэтому работал с ней лишь по вершкам.

P.S. Примеры и мнение, основанное на личном PL/SQL опыте нужны?
 

tony2001

TeaM PHPClub
>P.S. Примеры и мнение, основанное на личном PL/SQL опыте нужны?
да, это было бы отлично, особенно с использованием OCI8 в PHP.
если есть желание и возможность - сделай примеры в ман по работе с коллекциями, я буду очень благодарен.
 

fisher

накатила суть
K&T: мы видимо о разных вещах говорим. ты о реальной таблице, которая create table и в которой есть varray или table, а я про сами "массивы" которые create type.

имхо хранить объекты вне pl/sql-кода, куда-то там их возвращать в апликейшн и тд - нецелесообразно. практически уверен, всегда существует способ это обойти, причем решение будет более простым, надежным, масштабируемым. имхо.

tony: а не будут ли полезны примеры работы с коллекциями на C:
Oracle Call Interface Programmer's Guide,
11. Object-Relational Datatypes,
Collections (OCITable, OCIArray, OCIColl, OCIIter). на пхп нормальных примеров ни разу не видел
 

chira

Новичок
Автор оригинала: romutis
Вот здесь будет работать SELECT/INSERT/UPDATE/DELETE для таблицы TEST - но вы не сможете сделать UPDATE/INSERT/DELETE для отдельных элементов столбцов column_varray или column_table в отдельности от.
Если быть до конца точным, то невозможность применения DML относиться только к column_varray.
Код:
INSERT INTO test VALUES (1,my_varray('aaaa','bbbbb','Acccc','Addddd','Aeeeeee'),my_table('Tfffffff','Tgggggggg','Thhhhhhh'));
INSERT INTO test VALUES (2,my_varray('iiiiii','jjjjjjj','Akkkkkkk','Allllll','Ammmmmm'),my_table('Tnnnnnnnn','Toooo','Tppppppppp','rrrrrrrr','sssssss'));

SELECT ind,column_varray,column_table FROM test;
SELECT * FROM TABLE(SELECT column_varray FROM test WHERE ind = 1);

SELECT * FROM TABLE(SELECT column_table FROM test WHERE ind = 2);

SELECT * FROM TABLE(SELECT column_table FROM test WHERE ind = 1);

UPDATE TABLE(SELECT column_table FROM test WHERE ind = 2) SET column_value='zzzzzzzzzzzzzz'
WHERE column_value='Toooo';

INSERT INTO 
TABLE(SELECT column_table FROM test WHERE ind = 1)
VALUES('Modern');

DELETE FROM TABLE(SELECT column_table FROM test WHERE ind = 1)
WHERE column_value='aaaa' ;
 

K&T

Guest
Уважаемые ГУРУ, как-то разговор из практической плоскости перешел в теоретическую и растворился в богатстве предлагаемого ORACLE инструментария. Может все таки кто-то скажет как отфетчить результат запроса
SELECT GET_NUMBER_LIST() FROM DUAL; Функция GET_NUMBER_LIST() возвращает тип - TABLE of NUMBER.
 

chira

Новичок
тип должен быть создан как:
CREATE TYPE MyType AS TABLE OF NUMBER;
тогда если функция возвращает MyType, то:
Код:
SELECT * FROM TABLE(CAST(GET_NUMBER_LIST() as MyType))
 

chira

Новичок
Код:
SQL> CREATE OR REPLACE TYPE MyType AS TABLE OF NUMBER
  2  /

Type created.

SQL> CREATE OR REPLACE FUNCTION GET_NUMBER_LIST RETURN myType IS
  2   v_1 MyType:=MyType(1,2,5,6,7,3245,2345,567,678,34,0);
  3  BEGIN
  4   RETURN v_1;
  5  END;
  6  /

Function created.

SQL> SELECT * FROM TABLE(CAST(GET_NUMBER_LIST() as MyType));

COLUMN_VALUE
------------
           1
           2
           5
           6
           7
        3245
        2345
         567
         678
          34
           0

11 rows selected.
SQL>
 

K&T

Guest
Спасибо за совет, но в SQLе у меня и до этого все работало, а вот если я выполнял подобную конструкцию в PHP то на строчке OCIFETCH($stmt) все валиться наглухо, причем как то не особенно объясняя что случилось.
 

K&T

Guest
Ой пардон вру, у меня валиться если я говорю
SELECT GET_NUMBER_LIST() AS RESULT FROM DUAL, через таблицу сейчас попробую.
 

K&T

Guest
$sql = "SELECT GET_NUMBER_LIST() AS RESULT FROM DUAL";
$stmt = ociparse($conn, $sql);
ociexecute($stmt);
while (ocifetch($stmt))
{$result = ociresult($stmt, "RESULT"); .....}
Вот так было раньше - не работает железно :(
 

tony2001

TeaM PHPClub
PHP:
/*
PL/SQL был тупо copy/paste из поста chir'ы
*/

$connection = oci_connect("user","pswd","server");
$statement = oci_parse($connection,"
			begin
				:result := PK_TEST.get_number_list();
			end;
		");
//создаем коллекцию
$collection = oci_new_collection($connection,"MYTYPE"));

//биндим
oci_bind_by_name($statement,":result", $collection, -1, OCI_B_NTY);

//выполняем
oci_execute($statement,OCI_DEFAULT);

//печатаем
for($i = 0, $size = $collection->size(); $i < $size; $i++) {	
	echo $collection->getelem($i)."<br>";
}
заработало =)

принимаются пожелания по поводу имени метода getelem() коллекции.
меня от этого имени тошнит =(
getElement() ?
просто get() ?
 

tony2001

TeaM PHPClub
соврал.
PL/SQL не тупо скопировал - функцию добавил в пакет, а не просто так создал.
 

K&amp;T

Guest
Спасибо, все понял, буду преобразовывать CASTом массив в таблицу. Для меня это самый простой и понятный вариант.
 

K&amp;T

Guest
А что за метод такой getelem, поискал на php.net, там ответили жестко и однозначно -
Sorry, but the function getelem is not in the online manual.
 

tony2001

TeaM PHPClub
[m]ocicollgetelem[/m] - он так в оригинале зовется.
в PHP5 - oci_collection_element_get();
 
Сверху