Карта-подобный тип объекта в PL / SQL? - PullRequest
6 голосов
/ 15 июня 2009

Я хочу написать подобный карте тип объекта в PL / SQL. Я имею в виду список пар ключ-значение, где значение может быть другим списком пар ключ-значение. Просто или так я думал. Вот два упрощенных

CREATE OR REPLACE TYPE TKey AS OBJECT
(
    name varchar2(240),
    value_text varchar2(2000),
    value_map TMap
)

CREATE OR REPLACE TYPE TMap AS TABLE OF TKey

Может быть, не все так просто, потому что теперь у меня есть проблема "Цыпленок или яйцо". Если я сначала введу TKey, он пожалуется, что TMap не определен. Если я сначала введу TMap, он пожалуется, что TKey не определен. Если я вставлю TKey и пропущу строку value_map, затем добавлю тип TMap, затем попытаюсь заменить тип TKey, он не допустит этого.

Мне не повезло? Разве такая конструкция невозможна в PL / SQL?

Заранее спасибо

Разъяснение: То, что я хочу, это то, что может дать мне это: Карта, содержащая ключи a, b и c. Значение a - это varchar «привет», значение b - это varchar «мир», а значение c - это другая карта с ключами x и y, а значение x - это «что» и значение когда ты "вверх".

Вот как это будет выглядеть в Java:

Map<String, Object> map = new HashMap<String, Object>();
map.set("a", "Hello");
map.set("b", "World");
Map<String, Object> child = new HashMap<String, Object>();
child.set("x", "What's");
child.set("y", "up");
map.set("c", child);

Теперь я знаю, что что-то вроде «объекта», поскольку возможность хранить что-либо невозможно. Мне нужен объект, который может хранить список объектов того же типа, что и этот объект. В общем, дерево, да.

Ответы [ 3 ]

15 голосов
/ 15 июня 2009

Вы можете использовать ассоциативные массивы. Из руководства пользователя PL / SQL:

Понимание ассоциативных массивов (таблицы-указатели)

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

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

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

Пример 5-1 Объявление типов коллекции

DECLARE  TYPE population_type IS TABLE OF NUMBER INDEX BY VARCHAR2(64);
  country_population population_type;
  continent_population population_type;
  howmany NUMBER;
  which VARCHAR2(64);
BEGIN
  country_population('Greenland') := 100000; -- Creates new entry
  country_population('Iceland') := 750000;   -- Creates new entry
-- Looks up value associated with a string
  howmany := country_population('Greenland');
  continent_population('Australia') := 30000000;
  continent_population('Antarctica') := 1000; -- Creates new entry
  continent_population('Antarctica') := 1001; -- Replaces previous value 
-- Returns 'Antarctica' as that comes first alphabetically.
  which := continent_population.FIRST;
-- Returns 'Australia' as that comes last alphabetically.  which := continent_population.LAST;
-- Returns the value corresponding to the last key, in this
-- case the population of Australia.
  howmany := continent_population(continent_population.LAST);
END;
/
4 голосов
/ 15 июня 2009

Возможно, вам нужно думать более относительно:)

Вместо хранения TMap (value_map) внутри типа TKey, просто сохраните value_map_name, который затем можно использовать для поиска другой записи в таблице.

CREATE OR REPLACE TYPE TKey AS OBJECT(
 name varchar2(240),
 value_text varchar2(2000),
 value_map_name varchar2(240));

Затем вы можете использовать ассоциативные массивы (согласно ответу мамбокинга) для их хранения.

1 голос
/ 15 июня 2009

Вы пытаетесь втиснуть парадигму ключ-значение в реляционную СУБД, которая не имеет логического смысла. Было бы намного проще перейти к чисто реляционным отношениям:

CREATE TABLE key_value AS
(
    key varchar2(240),        -- PRIMARY KEY
    value_text varchar2(2000)
);

CREATE TABLE key_hierarchy AS
(
    child_key varchar2(240), -- PRIMARY KEY, FOREIGN KEY to key_value.key
    parent_key varchar2(240) -- FOREIGN KEY to key_value.key
);

И это все! Если позже вы захотите изменить, что у ребенка может быть много родителей, просто измените ограничение PK (красота реляционных СУБД)

...