2012-06-19 9 views
8

Given stół jak:Jak stworzyć not null kolumny w widoku

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

Chcę utworzyć widok jak:

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

Tylko gdzie kolumna "MyColumn" nie jest” ZERO".

W SQL Server jest dość prosta:

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

Jednak Oracle równoważne wyniki w "null" kolumna:

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

Czy mimo to zmusić Oracle, aby zaznaczyć kolumnę widoku za jako "NOT NULL" w metadanych?

+1

Krzyżyk opublikowany w DBA.SE: http://dba.stackexchange.com/questions/19484/oracle-how-to-create-a-not-null-column-in-a-view –

+0

In w tym przypadku kolumna w widoku nie może mieć wartości null, jeśli podstawowa kolumna tabeli ma ograniczenie nie-puste. Czy chcesz 'desc" MyView "' (mam nadzieję, że tak naprawdę nie używasz nazw obiektów o różnych nazwach!), Aby pokazać to również jako not-null? –

+0

Tak, chcę metadane, aby pokazać go jako not-null. (I nie, to nie są prawdziwe konwencje nazewnictwa). –

Odpowiedz

6

Nie można dodać ograniczenia zerowego ani ograniczenia kontrolnego do widoku; patrz: this i na tej samej stronie "Ograniczenia w przypadku ograniczeń NULL" i "Ograniczenia przy sprawdzaniu ograniczeń". Do widoku można dodać klauzulę with check option (względem klauzuli redundant where), ale nie zostanie ona oznaczona jako not null w słowniku danych.

Jedynym sposobem mogę myśleć, aby uzyskać ten efekt jest, jeśli jesteś na 11g, aby dodać wartość do roli kolumnie wirtualnym na stole, i (jeśli to jeszcze potrzebne) utworzyć widok przeciwko temu:

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 

Skoro powiedział w komentarzu dba.se, że jest to dla wyśmianie coś, można użyć zwykłej kolumny i spust do symulacji kolumny wirtualny:

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 

i desc "MyView" wciąż daje:

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

Jak wspomniano Leigh (także na dba.se), jeśli nie chcesz, aby wstawić/zaktualizować widok można użyć instead of spust, z VC lub fałszywej wersji.

+0

Dodano więc kolumnę obliczeniową do tabeli z rzutowaniem i nie zerowym ograniczeniem, w ten sposób widok nie wymaga rzutowania. - Spróbuję to jak najszybciej. Czy nowa kolumna jest zapisywalna? (Czy może zaktualizować oryginalną kolumnę?) –

+0

Nie, nie można wstawić do VC na stole (ponieważ jest on generowany); i nie można wstawić do widoku, ponieważ jest to sprzeczne z VC. Dostaniesz ORA-54013 na 'insert' lub ORA-54017 na' update'. (Ale pojawia się ten sam błąd w stosunku do oryginalnego widoku, z "rzutem", jeśli VC istnieje, a ORA-01733, jeśli nie). –

+0

Wystarczająco dobre na razie :-) (Przynajmniej dopóki Oracle nie powierzy mapowania "numeru", aby "podwoić" w swoim dostawcy EF, dopóki nie przeprowadzimy migracji z Oracle.) –

1

Jeśli użytkownik może mieć ograniczenie NOT NULL na kolumnie widoku, uważam, że SELECT z widoku nie powiedzie się, jeśli kolumna ma wartość NULL. Jeśli jest to intencją następnie dodaje może dać ci to, czego szukasz:

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; 

niezbyt atrakcyjne, a otrzymasz brzydki „ORA-01476: podział jest równy zeru” wiadomość, jeśli oddział ELSE CASE jest brany pod uwagę, ale być może jest to krok na drodze do "lepszego".

Udostępnij i ciesz się.


EDIT: Jeśli celem jest tylko odebrać wiersze, gdzie kolumna docelowa nie jest null może można dodać klauzulę WHERE do widzenia, jak w:

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: Patrząc na przykład SQL Server, wydaje się, że funkcja ISNULL jest używany w celu zapewnienia, że ​​kolumna nigdy nie jest NULL. Jeśli jest to dopuszczalne można wykonać następujące czynności:

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; 

Cytując Bullwinkle „Ten czas fer pewno !!!” :-)

+0

Wartość nie może być pusta, więc wybór nie może zawieść, chcę tylko, aby metadane to odzwierciedlały. –

+0

Rozumiem, jak się czujesz. Domyślna kolumna tabeli jest najlepszą opcją dla ograniczenia NOT NULL. –

+0

@DannyVarod: dodano trzecią opcję użycia NVL wraz z CAST, która jest mniej więcej odpowiednikiem ISNULL używanej w przykładzie SQL Server w oryginalnym wpisie. –

Powiązane problemy