I get an error while writing the IIF statement, table and the statement given below.
Statement:
SELECT IIF(EMP_ID=1,'True','False') from Employee;
Table:
CREATE TABLE SCOTT.EMPLOYEE
(
EMP_ID INTEGER NOT NULL,
EMP_FNAME VARCHAR2(30 BYTE) NOT NULL,
EMP_LNAME VARCHAR2(30 BYTE) NOT NULL,
EMP_ADDRESS VARCHAR2(50 BYTE) NOT NULL,
EMP_PHONE CHAR(10 BYTE) NOT NULL,
EMP_GENDER CHAR(1 BYTE)
)
Error:
00907-missing right parantheses
Please provide your inputs.
Oracle doesn't provide such IIF Function.
Instead, try using one of the following alternatives:
DECODE Function:
SELECT DECODE(EMP_ID, 1, 'True', 'False') from Employee
CASE Function:
SELECT CASE WHEN EMP_ID = 1 THEN 'True' ELSE 'False' END from Employee
Two other alternatives:
a combination of NULLIF and NVL2. You can only use this if emp_id is NOT NULL, which it is in your case:
select nvl2(nullif(emp_id,1),'False','True') from employee;
simple CASE expression (Mt. Schneiders used a so-called searched CASE expression)
select case emp_id when 1 then 'True' else 'False' end from employee;
In PL/SQL, there is a trick to use the undocumented OWA_UTIL.ITE function.
SET SERVEROUTPUT ON
DECLARE
x VARCHAR2(10);
BEGIN
x := owa_util.ite('a' = 'b','T','F');
dbms_output.put_line(x);
END;
/
F
PL/SQL procedure successfully completed.
Related
I am creating a function using types, it gives me two errors saying:
Error(12,7): PL/SQL: SQL Statement ignored
Error(27,13): PL/SQL: ORA-00904: "UT": invalid identifier
I can't see any issues with my code as shown below, any help?
CREATE OR REPLACE EDITIONABLE FUNCTION ESF_GET_USERS
RETURN tc_users
IS
l_users tc_users;
BEGIN
SELECT t_user
(
Uname,
FName,
Sname,
PName,
Tit,
mail,
FC,
SC,
SN,
SD,
RC,
RN,
CC || ' ' || CN,
UT
)
BULK COLLECT INTO l_users
FROM USERS_MV;
RETURN l_users;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001,'No records returned');
END esf_users;
I am creating two types, one is an object and the second is a table from that object as shown below:
CREATE OR REPLACE EDITIONABLE TYPE T_USER
AS OBJECT
(
UNAME VARCHAR2(20 BYTE),
FNAME VARCHAR2(30 BYTE),
SNAME VARCHAR2(30 BYTE),
PNAME VARCHAR2(30 BYTE),
TIT VARCHAR2(30 BYTE),
MAIL VARCHAR2(24 BYTE),
FC VARCHAR2(10 BYTE),
SC VARCHAR2(10 BYTE),
SN VARCHAR2(200 BYTE),
SD VARCHAR2(10 BYTE),
RC VARCHAR2(10 BYTE),
RN VARCHAR2(200 BYTE),
HN VARCHAR2(100 BYTE),
UT VARCHAR2(7 BYTE)
);
CREATE OR REPLACE EDITIONABLE TYPE TC_USERS AS TABLE OF t_user;
The Materialized view code is:
CREATE MATERIALIZED VIEW "USERS_MV"
AS select "UName",
"FName",
"Sname",
"PName",
"Tit",
"mail",
"FC",
"SC",
"SN",
"SD",
"RC",
"RN",
"CC",
"CN",
"UT"
from (
SELECT ...
Looks like a classic mistake in Oracle - never enclose anything into double quotes. If you do it once (at the time of creation of that object), you have to do it always.
SQL> create table test ("Id" number);
Table created.
SQL> select id from test;
select id from test
*
ERROR at line 1:
ORA-00904: "ID": invalid identifier
SQL> select ID from test;
select ID from test
*
ERROR at line 1:
ORA-00904: "ID": invalid identifier
SQL> select "ID" from test;
select "ID" from test
*
ERROR at line 1:
ORA-00904: "ID": invalid identifier
SQL> select "Id" from test;
no rows selected
SQL>
I suggest you recreate everything - remove double quotes. Oracle will store names using UPPPERCASE, but you can reference objects/columns using any case you want.
I have a package with a INSERT in a sp, and I want to return the id of that insert. The table have a sequence and a trigger for the identity, but in the sp I don't know how can I return the id of the insert that i'm doing, because in the code java I need to use it.
CREATE OR REPLACE PACKAGE BODY PLUSALT.INSERTAR
IS
PROCEDURE INSERTAR_ESTRATEGIA(
P_USUARIO IN VARCHAR2,
P_CAMPAÑA IN NUMBER,
P_FKPLANTILLA IN NUMBER,
P_NOMBRE IN VARCHAR2)
IS
BEGIN
INSERT
INTO ESTRATEGIA VALUES
(
NULL,
P_CAMPAÑA,
P_USUARIO,
P_FKPLANTILLA,
P_NOMBRE,
NULL,
SYSDATE,
1,
'Y'
);
END;
END;
/
Ths is the table
CREATE TABLE ESTRATEGIA
(
ESID NUMBER(25) NOT NULL,
FK_CAMPAÑA NUMBER(5) NOT NULL,
FK_USUARIO NUMBER(8) NOT NULL,
FK_PLANTILLAESTRA NUMBER(8),
ESNOMBRE VARCHAR2(100),
ESDESCRIPCION VARCHAR2(300),
ESFCHCREACION DATE,
FKESTADO NUMBER(3) NOT NULL,
ESACTIVA CHAR(1)
)
;
The sequence
CREATE SEQUENCE ESTRATEGIA_SEC
START WITH 1
INCREMENT BY 1
NOMAXVALUE;
The trigger
CREATE TRIGGER TRIG_ESTRATEGIA
BEFORE INSERT ON ESTRATEGIA
FOR EACH ROW
BEGIN
SELECT ESTRATEGIA_SEC.nextval INTO :new.ESID FROM dual;
END
;
USE RETURNING INTO in the insert with an OUT parameter. Use this parameter P_ESID in your java code.
CREATE OR REPLACE PACKAGE BODY PLUSALT.INSERTAR
IS
PROCEDURE INSERTAR_ESTRATEGIA(
P_USUARIO IN VARCHAR2,
P_CAMPAÑA IN NUMBER,
P_FKPLANTILLA IN NUMBER,
P_NOMBRE IN VARCHAR2,
P_ESID OUT NUMBER)
IS
BEGIN
INSERT
INTO ESTRATEGIA VALUES
(
NULL,
P_CAMPAÑA,
P_USUARIO,
P_FKPLANTILLA,
P_NOMBRE,
NULL,
SYSDATE,
1,
'Y'
) RETURNING ESID INTO P_ESID ;
END;
END;
/
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/returninginto_clause.htm
Quick demonstration.
SQL> create table t (id int);
Table created.
SQL> create sequence s;
Sequence created.
SQL> var x number
SQL> insert into t values(s.nextval) returning id into :x;
1 row created.
SQL> print x
X
----------
1
I have a table with 75+ columns in it.
Almost all of the columns have the NOT NULL constraint.
If do a giant alter table modify statement (with every column in there), I get an error saying something along the lines of "You can't set this field to NULL, because it already is NULL"
I have to do this for several tables, and so would prefer to have a dynamic solution.
Can I dynamically find all of the columns that are NOT NULL, and set them to NULL?
I've seen several similar questions like this, but can't find a solution for Oracle SQL.
Modify all columns in a table to 'not null' no matter what
Here is a test table, with two not null columns, and one null column:
create table zzz_mark_test_me (
cust_id varchar2(20) not null,
cust_name varchar2(20) null,
cust_phone varchar2(20) not null
);
table ZZZ_MARK_TEST_ME created.
desc zzz_mark_test_me
Name Null Type
---------- -------- ------------
CUST_ID NOT NULL VARCHAR2(20)
CUST_NAME VARCHAR2(20)
CUST_PHONE NOT NULL VARCHAR2(20)
Now invoke this SQL:
select 'alter table ' || table_name ||
' modify (' || column_name || ' null );'
from user_tab_columns
where table_name='ZZZ_MARK_TEST_ME' and nullable='N'
order by column_id;
Which yields this:
alter table ZZZ_MARK_TEST_ME modify (CUST_ID null );
alter table ZZZ_MARK_TEST_ME modify (CUST_PHONE null );
Copy/paste the output into SQL*Plus etc. and invoke:
alter table ZZZ_MARK_TEST_ME modify (CUST_ID null );
table ZZZ_MARK_TEST_ME altered.
alter table ZZZ_MARK_TEST_ME modify (CUST_PHONE null );
table ZZZ_MARK_TEST_ME altered.
And now, no more NOT NULL:
desc zzz_mark_test_me
Name Null Type
---------- ---- ------------
CUST_ID VARCHAR2(20)
CUST_NAME VARCHAR2(20)
CUST_PHONE VARCHAR2(20)
You can use this procedure. You can first comment out line containing "execute immediate" to see what it executes, before running.
First parameter is schema_name, second is table_name.
create or replace procedure proc_null(t_owner in varchar2, t_name in varchar2) as
v_exec_imm varchar2(1000);
begin
for o in (select owner, column_name from all_tab_cols where owner=t_owner and table_name=t_name and nullable = 'N')
loop
v_exec_imm := 'alter table '||t_owner||'.'||t_name||' modify ('||o.column_name||' null) ';
execute immediate v_exec_imm; -- comment this line if You want, modifies table
dbms_output.put_line( v_exec_imm );
end loop;
end proc_null;
I'm writing a function for batch-importing data into our org-chart. It seems to work fine for retrieving entries that already exists, but when an entry does not already exist, and it's supposed to insert, commit, and return the result of a re-attempt (so as to get the auto-generated ID), it always returns NULL.
I'm sure I'm doing something wrong here, but what? Help appreciated.
Note: there's a before-insert trigger that fills in DEPT_ID if it's not specified. Works fine if the insert statement is executed by hand.
CREATE TABLE DEPTS
(
"DEPT_ID" VARCHAR2(10 BYTE),
"HEADER_ID" VARCHAR2(10 BYTE),
"COMMENTS" VARCHAR2(100 BYTE),
"CATEGORY" VARCHAR2(2 BYTE)
);
CREATE OR REPLACE FUNCTION get_or_make_unit(
, in_cat VARCHAR2
, in_cmt VARCHAR2
, in_hdr VARCHAR2 DEFAULT NULL
) RETURN VARCHAR2 AS
unit_id VARCHAR2(10);
BEGIN
unit_id := NULL;
IF in_hdr IS NULL THEN
SELECT dept_id
INTO unit_id
FROM depts unit
WHERE unit.category = in_cat
AND unit.comments = in_cmt
AND unit.header_id IS NULL;
ELSE
SELECT dept_id
INTO unit_id
FROM depts unit
WHERE unit.category = in_cat
AND unit.comments = in_cmt
AND unit.header_id = in_hdr;
END IF;
IF unit_id IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Inserting!');
INSERT INTO depts (
header_id
, comments
, category
) VALUES (
in_hdr
, in_cmt
, in_cat);
COMMIT;
unit_id := get_or_make_unit(in_cat, in_cmt, in_hdr);
RETURN unit_id;
ELSE
DBMS_OUTPUT.PUT_LINE('Not inserting!');
RETURN unit_id;
END IF;
END get_or_make_unit;
And the trigger:
CREATE OR REPLACE TRIGGER HRD.DEPTS_BIR
BEFORE INSERT
ON HRD.DEPTS
FOR EACH ROW
DECLARE
JML NUMBER;
BEGIN
SELECT SEQ_DEPT_ID.NEXTVAL INTO JML FROM DUAL;
:NEW.DEPT_ID:='D'||to_char(JML);
END DEPTS_BIR;
Examples
This works:
INSERT INTO depts (
header_id
, comments
, category
) VALUES (
'D532'
, 'ACCOUNTING'
, '2');
COMMIT;
SELECT get_or_make_unit('2', 'ACCOUNTING', 'D532') FROM DUAL;
=> 'D533'
This does not:
SELECT get_or_make_unit('2', 'NEW DEPT', 'D532') FROM DUAL;
=> NULL
Instead of:
INSERT INTO depts (
header_id
, comments
, category
) VALUES (
in_hdr
, in_cmt
, in_cat);
COMMIT;
unit_id := get_or_make_unit(in_cat, in_cmt, in_hdr);
use RETURNING INTO:
INSERT INTO depts (
header_id
, comments
, category
) VALUES (
in_hdr
, in_cmt
, in_cat) RETURNING dept_id INTO unit_id;
COMMIT;
I think recursive call in not the best approach, but if you are strict of using it, then please post definition of mentioned before-insert trigger.
UPDATE: You cannot call functions containing DML operations from SQL statement. Please see this answer for details. Example of correct call:
DECLARE
unit_id varchar2(32);
BEGIN
unit_id := get_or_make_unit('2', 'NEW DEPT', 'D532');
dbms_output.put_line(unit_id);
END;
UPDATE2: Also you need to catch NO_DATA_FOUND exception that is raised when you call your function with not existent combination. Below is example:
CREATE OR REPLACE FUNCTION get_or_make_unit(in_cat VARCHAR2,
in_cmt VARCHAR2,
in_hdr VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2 AS
unit_id VARCHAR2(10);
BEGIN
unit_id := NULL;
IF in_hdr IS NULL THEN
SELECT dept_id
INTO unit_id
FROM depts unit
WHERE unit.category = in_cat
AND unit.comments = in_cmt
AND unit.header_id IS NULL;
ELSE
SELECT dept_id
INTO unit_id
FROM depts unit
WHERE unit.category = in_cat
AND unit.comments = in_cmt
AND unit.header_id = in_hdr;
END IF;
DBMS_OUTPUT.PUT_LINE('Not inserting!');
RETURN unit_id;
exception
when NO_DATA_FOUND then
DBMS_OUTPUT.PUT_LINE('Inserting!');
INSERT INTO depts
(header_id, comments, category)
VALUES
(in_hdr, in_cmt, in_cat)
returning dept_id into unit_id;
COMMIT;
RETURN unit_id;
END get_or_make_unit;
Your call to get_or_make_unit appears to be missing the first parameter.
INSERT INTO depts (
header_id
, comments
, category
) VALUES (
in_hdr
, in_cmt
, in_cat);
This code is not inserting anything into dept_id of depts table. Thats the reason you are getting null
Here I want to check if record exists and based on that I want perform actions.
My code is as below
FOR cell_configs IN (SELECT cc.cell_configuration_name,
cc.cell_configuration_value
from cell_configurations cc
where (cc.cell_configuration_name like height_cc or
cc.cell_configuration_name like width_cc) and
cc.cell_id=c_id)
LOOP
if cc.cell_configuration_name OR
cc.cell_configuration_value EXISTS
then
-- i want to update the table dbms_output.put_line(temp || ' does exist');
else
-- i want to insert records into the table dbms_output.put_line(temp || ' does not exist');
end if;
dbms_output.put_line(c_id || ' ' ||
cell_configs.cell_configuration_name || ' ' ||
cell_configs.cell_configuration_value );
END LOOP;
If there are no records found I can see that I will get empty string i.e ''. I cannot check if it is null or not.
Can anybody help me on this please?.
EDIT (info copied from comments):
I am looking for these 2 rows(height,width) cell_configuration_name like 'container.dealer-content.configs[1].width' or cell_configuration_name like 'container.dealer-content.configs[1].height' cell_configuration_value=flex-width-8 cell_configuration_value=flex-width-250
CELL_CONFIGURATIONS table below
CELL_CONFIGURATION_ID NUMBER(38,0) PK
CELL_ID NUMBER(38,0) FK
CELL_CONFIGURATION_NAME VARCHAR2(100 BYTE)
CELL_CONFIGURATION_VALUE VARCHAR2(4000 BYTE)
IS_LOCKED CHAR(1 BYTE)
MODIFIED_BY VARCHAR2(100 BYTE)
MODIFIED_DATE DATE
CREATED_BY VARCHAR2(100 BYTE)
CREATED_DATE
Sample Data as Below
CELL_ID CELL_CONFIGURATION_NAME CELL_CONFIGURATION_VALUE
37771286880 container.dealer-content.configs[1].height flex-height-2
37771286880 container.dealer-content.configs[1].width flex-width-8
Here is the beggining of a solution...
BEGIN
FOR rec IN
(SELECT cell_id -- assuming that cell_id will repeat for lines with width and height
FROM CELL_CONFIGURATIONS
WHERE CELL_CONFIGURATION_NAME LIKE height_cc
MINUS
SELECT cell_id
FROM CELL_CONFIGURATIONS
WHERE CELL_CONFIGURATION_NAME LIKE width_cc
)
LOOP
-- INSERT STATEMENT
END LOOP;
END;