Oracle Object Relational Database вставляет записи в таблицу со ссылкой на производную таблицу - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть следующая структура ниже, и я хочу добавить запись в таблицу project. Проблема со следующей INSERT заключается в том, что вместо customer_t мне нужно выбрать запись из таблицы user при вставке, но я хочу выбирать только клиентов (а не сотрудников). В основном customer_t и staff_t наследуются от user_t (таблица: пользователь).

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

У меня не такой опыт работы с этим ORM. Есть идеи, как ее решить?

INSERT INTO project VALUES (
  1,
  'Project name',
  'Description',
  ( SELECT REF(u) AS customer_t
    FROM   "USER" u
    WHERE  idno = 1
    AND    VALUE(u) IS OF TYPE (customer_t)
  ),
  ( SELECT REF(s) FROM service s WHERE serviceno = 1)
);

Сообщение об ошибке:

Error starting at line : 1 in command -
INSERT INTO project VALUES (1, 'Project name', 'Logo', (SELECT REF(u) AS customer_t FROM "USER" u WHERE idno = 1 AND VALUE(u) IS OF TYPE (customer_t)), (SELECT REF(s) FROM service s WHERE serviceno = 1))
Error at Command Line : 1 Column : 72
Error report -
SQL Error: ORA-00932: inconsistent datatypes: expected REF C##EX_TEST.CUSTOMER_T got REF C##EX_TEST.USER_T
00932. 00000 -  "inconsistent datatypes: expected %s got %s"
*Cause:    
*Action:

SQL:

CREATE TYPE name_t AS OBJECT (
  first_name     VARCHAR2(32),
  last_name      VARCHAR2(32)
);

CREATE TYPE address_t AS OBJECT (
  province       VARCHAR2(32),
  street         VARCHAR2(32),
  city           VARCHAR2(32),
  postal_code    VARCHAR2(10)
);

CREATE TYPE user_t AS OBJECT (
  idno           NUMBER,
  email          VARCHAR2(40),
  password       VARCHAR2(32),
  name           name_t,
  address        address_t,
  phone          VARCHAR2(15),
  MAP MEMBER FUNCTION get_idno RETURN NUMBER
) NOT FINAL;

CREATE TYPE rank_t AS OBJECT (
  rankno       NUMBER,
  name         VARCHAR2(40),
  description  VARCHAR2(60)
);

CREATE TABLE "RANK" OF rank_t (
  PRIMARY KEY (rankno),
  UNIQUE (name)
);

INSERT INTO "RANK" VALUES (1, 'User', 'Simple a user');
INSERT INTO "RANK" VALUES (2, 'Manager', 'Manager');
INSERT INTO "RANK" VALUES (3, 'Administrator', 'Admin');

CREATE TYPE customer_t UNDER user_t (

);

CREATE TYPE staff_t UNDER user_t (
  salary       NUMBER(7,2),
  rank         REF rank_t
);

CREATE TABLE "USER" OF user_t (
  PRIMARY KEY (idno),
  UNIQUE (email));

CREATE TYPE service_t AS OBJECT (
  serviceno    NUMBER,
  name         VARCHAR2(40),
  description  VARCHAR2(60)
);

CREATE TABLE service OF service_t (PRIMARY KEY (serviceno));

CREATE TYPE project_t AS OBJECT (
  projectno    NUMBER,
  name         VARCHAR2(40),
  description  VARCHAR2(60),
  customer     REF customer_t,
  service      REF service_t
);

CREATE TABLE project OF project_t (PRIMARY KEY (projectno));

1 Ответ

2 голосов
/ 19 февраля 2020

Вам не нужна отдельная таблица для клиентов; просто вставьте типы в таблицу USER.

Если вы хотите указать клиента, введите customer_t тип:

INSERT INTO "USER" VALUES(
  customer_t(
    1,
    'person1@customer.example.com',
    'abcdefg',
    name_t( 'One', 'Uno' ),
    address_t( 'province','street', 'city', '12345' ),
    '0123456789'
  )
);

Если вы хотите вставить пользователя, то используйте user_t или вставьте значения без типа:

INSERT INTO "USER" VALUES(
    2,
    'person2@user.example.com',
    'abcdefg',
    name_t( 'Two', 'Dos' ),
    address_t( 'province','street', 'city', '12345' ),
    '0123456789'
);

Если вы хотите вставить сотрудника, используйте staff_t:

INSERT INTO "USER" VALUES(
  staff_t(
    3,
    'person3@staff.example.com',
    'abcdefg',
    name_t( 'Three', 'Tres' ),
    address_t( 'province','street', 'city', '12345' ),
    '0123456789',
    12345.67,
    (SELECT REF(r) FROM "RANK" r WHERE rankno = 2 )
  )
);

Тогда данные будут иметь правильные типы (которые можно извлечь с помощью SYS.ANYDATA) и использовать функцию TREAT для преобразования супертипа в подтип:

SELECT idno,
       email,
       SYS.ANYDATA.getTypeName( SYS.ANYDATA.convertObject( VALUE(u) ) ) As type,
       TREAT(VALUE(u) AS staff_t).salary AS salary,
       TREAT(VALUE(u) AS staff_t).rank.name AS rank
FROM   "USER" u

вывод:

IDNO | EMAIL                        | TYPE                                   |   SALARY | RANK   
---: | :--------------------------- | :------------------------------------- | -------: | :------
   1 | person1@customer.example.com | FIDDLE_KPHUNVHPVRKOYQBWVAQS.CUSTOMER_T |     <em>null</em> | <em>null</em>   
   2 | person2@user.example.com     | FIDDLE_KPHUNVHPVRKOYQBWVAQS.USER_T     |     <em>null</em> | <em>null</em>   
   3 | person3@staff.example.com    | FIDDLE_KPHUNVHPVRKOYQBWVAQS.STAFF_T    | 12345.67 | Manager

и:

SELECT idno,
       email
FROM   "USER" u
WHERE  VALUE(u) IS OF TYPE (customer_t)

выходы:

IDNO | EMAIL                       
---: | :---------------------------
   1 | person1@customer.example.com

и ваша вставка должна преобразовать REF от супертипа user_t до подтипа customer_t с использованием функции TREAT :

INSERT INTO project VALUES (
  1,
  'Project name',
  'Description',
  ( SELECT TREAT( REF(u) AS REF customer_t )
    FROM   "USER" u
    WHERE  idno = 1
    AND    VALUE(u) IS OF TYPE (customer_t)
  ),
  ( SELECT REF(s) FROM service s WHERE serviceno = 1)
);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...