Как создать столбец not null в представлении

учитывая таблицу, как:

CREATE TABLE "MyTable" 
(
  "MyColumn" NUMBER NOT NULL
);

Я хочу создать вид типа:

CREATE VIEW "MyView" AS
SELECT
    CAST("MyColumn" AS BINARY_DOUBLE) AS "MyColumn"
FROM "MyTable";

только где столбец "столбец mycolumn компонент компонент" "не нулевой".

в SQL Server это довольно прямолинейно:

CREATE VIEW [MyView] AS
SELECT
    ISNULL(CAST([MyColumn] AS Float), 0.0) AS [MyColumn]
FROM [MyTable];

однако эквивалент Oracle приводит к столбцу "NULL":

CREATE VIEW "MyView" AS
SELECT
    NVL(CAST("MyColumn" AS BINARY_DOUBLE), 0.0) AS "MyColumn"
FROM "MyTable";

есть ли в любом случае заставить Oracle пометить столбец представления как "не NULL" в метаданных?

2 ответов


вы не можете добавить в представление ограничение not null или check; см. этой и на той же странице "ограничения на не нулевые ограничения" и "ограничения на ограничения проверки". Вы можете добавить with check option (против избыточного предложения where) для представления, но это не будет отмечено как not null в словарь данных.

единственный способ, которым я могу думать, чтобы получить этот эффект, если вы находитесь на 11g, чтобы добавить значение приведения в качестве виртуального столбца в таблице и (если это все еще необходимо) создать мнение против этого:

ALTER TABLE "MyTable" ADD "MyBDColumn" AS
    (CAST("MyColumn" AS BINARY_DOUBLE)) NOT NULL;

CREATE OR REPLACE VIEW "MyView" AS
SELECT
    "MyBDColumn" AS "MyColumn"
FROM "MyTable";

desc "MyView"

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 MyColumn                                  NOT NULL BINARY_DOUBLE

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

CREATE TABLE "MyTable" 
(
  "MyColumn" NUMBER NOT NULL,
  "MyBDColumn" BINARY_DOUBLE NOT NULL
);

CREATE TRIGGER "MyTrigger" before update or insert on "MyTable"
FOR EACH ROW
BEGIN
    :new."MyBDColumn" := :new."MyColumn";
END;
/

CREATE VIEW "MyView" AS
SELECT
    "MyBDColumn" AS "MyColumn"
FROM "MyTable";

INSERT INTO "MyTable" ("MyColumn") values (2);

SELECT * FROM "MyView";

  MyColumn
----------
  2.0E+000

и desc "MyView" все-таки дает:

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 MyColumn                                  NOT NULL BINARY_DOUBLE

как упоминал ли (также на dba.se), если вы хотите вставить/обновить представление, вы можете использовать instead of триггер, с VC или поддельной версией.


Если вы может имеют ограничение NOT NULL для столбца представления я считаю, что выбор из представления затем завершится ошибкой, если столбец, о котором идет речь, равен NULL. Если это намерение, то следующее может дать вам то, что вы ищете:

CREATE OR REPLACE VIEW some_view AS
  SELECT some_field,
         some_other_field,
         CASE
           WHEN field_of_interest IS NOT NULL
             THEN CAST(field_of_interest AS BINARY_DOUBLE)
             ELSE 1 / 0
         END AS field_of_interest_not_null
     FROM some_table;

не очень привлекательно, и вы получаете уродливое сообщение "ORA-01476: деление равно нулю", если взята другая ветвь дела, но, возможно, это шаг на пути к "лучшему".

поделиться и наслаждаться.


EDIT: если цель состоит только в том, чтобы забрать строки, где ваш целевой столбец не равен нулю, возможно, вы могли бы добавить предложение WHERE в свое представление, как в:

CREATE OR REPLACE VIEW some_view AS
  SELECT some_field,
         some_other_field,
         CAST(field_of_interest AS BINARY_DOUBLE) AS field_of_interest
    FROM some_table
    WHERE field_of_interest IS NOT NULL;

YMMV.


EDIT2: В Примере SQL Server показано, что функция ISNULL используется для обеспечения того, чтобы столбец никогда не был NULL. Если это приемлемо, вы можете сделать следующее:

CREATE OR REPLACE VIEW some_view AS
  SELECT some_field,
         some_other_field,
         CAST(NVL(field_of_interest, 0.0) AS BINARY_DOUBLE) AS field_of_interest
    FROM some_table
    WHERE field_of_interest IS NOT NULL;

цитата Буллвинкля", на этот раз уверен, Фер!!!" :-)