PL/SQL: SQL Statement ignored and invalid identifier issues - oracle

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.

Related

Alter statement datatype update taking long time

i have tried to update the datatype from BYTE to CHAR instantly all columns(Around 100+ columns) updated.
but when i tried to rollback CHAR to BYTE its slowly loading for particular table which has around 87 million records.
right now my idea is to create one temp table and copy the data to temp table and drop that original table and recreate with updated datatype.it is good because copying to temp table millions of records takes long time for multiple table that im going to do.
any suggestion?
Converting from byte to char is "instaneous" because we in effect increasing the size of the column. Converting back is (potentially) a reduction and hence we need to check the existing data.
However, most likely we're not really changing the data, we're just checking it - so you can see that by checking the redo before and after such an operation. Here's on a 25million row table
SID_STAT# NAME VALUE
---------- -------------------------------------------------------------------------------- ----------
313 redo size 5580874020
SQL> alter table t modify c1 varchar2(100 byte);
Table altered.
SID_STAT# NAME VALUE
---------- -------------------------------------------------------------------------------- ----------
313 redo size 5580877992
If you can't afford to take the time (that the table is locked) then as has been suggested, dbms_redefinition here probably will help, but don't forget - this will move all of the data.
SQL> desc t
Name Null? Type
----------------------------------------- -------- ----------------------------
PK NUMBER(38)
C1 VARCHAR2(100 CHAR)
C2 VARCHAR2(100 CHAR)
C3 VARCHAR2(100 CHAR)
C4 VARCHAR2(100 CHAR)
C5 VARCHAR2(100 CHAR)
C6 VARCHAR2(100 CHAR)
C7 VARCHAR2(100 CHAR)
SQL> create table t1 (
2 pk int,
3 c1 varchar2(100 byte),
4 c2 varchar2(100 byte),
5 c3 varchar2(100 byte),
6 c4 varchar2(100 byte),
7 c5 varchar2(100 byte),
8 c6 varchar2(100 byte),
9 c7 varchar2(100 byte)
10 )
11 tablespace largetmp;
Table created.
SQL> exec dbms_redefinition.start_redef_table(user, 'T', 'T1');
PL/SQL procedure successfully completed.
SQL> set serveroutput on
SQL> declare
2 l_err pls_integer;
3 begin
4 dbms_redefinition.copy_table_dependents(
5 uname => user,
6 orig_table => 'T',
7 int_table => 'T1',
8 num_errors => l_err);
9 dbms_output.put_line('l_err=' || l_err);
10 end;
11 /
l_err=0
PL/SQL procedure successfully completed.
SQL>
SQL> exec dbms_redefinition.finish_redef_table(user, 'T', 'T1');
PL/SQL procedure successfully completed.
SQL>
SQL> desc t
Name Null? Type
----------------------------------------- -------- --------------
PK NOT NULL NUMBER(38)
C1 VARCHAR2(100)
C2 VARCHAR2(100)
C3 VARCHAR2(100)
C4 VARCHAR2(100)
C5 VARCHAR2(100)
C6 VARCHAR2(100)
C7 VARCHAR2(100)

PLS-00225: subprogram or cursor 'CHR' reference is out of scope

i make a procedure in plsql it return this error anyone know about it i post my code and error snap shot here
CREATE OR REPLACE PROCEDURE CHR.ATT_INSERT_TEST
IS
CURSOR ATT
IS
SELECT emp.EMPLOYEE_ID EMPLOYEE_ID,
io.CHECKTYPE CHECKTYPE,
io.MACHINE_NUM MACHINE_NUM,
io.ATT_ID ATT_ID,
io.SWIPE_DATE SWIPE_DATE,
io.SWIPE_TIME SWIPE_TIME
FROM INOUT_LIVE_MACHINE_TEST io, CHR_EMGT_EMPLOYEE emp
WHERE emp.EMPLOYEE_CODE = io.EMPLOYEE_CODE
AND io.ATT_ID NOT IN (SELECT ATT_ID_REF
FROM CHR_TA_EMP_SWIPE_IN_OUT
WHERE io.ATT_ID = ATT_ID_REF);
BEGIN
FOR I IN ATT
LOOP
INSERT INTO CHR_TA_EMP_SWIPE_IN_OUT (EMPLOYEE_ID,
SWIPE_DATE,
SWIPE_TIME,
SWIPE_ID,
SWIPE_TYPE,
CREATED_BY,
CREATION_DATE,
CLIENT_IP)
VALUES (I.EMPLOYEE_ID,
TO_DATE (i.SWIPE_DATE, 'MM/DD/YYYY'),
I.SWIPE_TIME,
CHR_TA_SWIPE_IN_OUT_SEQ.NEXTVAL,
I.CHECKTYPE,
I.EMPLOYEE_ID,
TO_DATE (i.SWIPE_DATE, 'MM/DD/YYYY'),
'192.168.0.71'
);
END LOOP;
COMMIT;
END;
/
this is my procedure i make subquery mostly time but this time it return me this kind of error.
i think this error show some issue is regarding alias but i already define alias for each column
i read this artical but my code is still stuck
PLS-00402: alias required in SELECT list of cursor to avoid duplicate column names
this is my table structure
CREATE TABLE CHR.CHR_TA_EMP_SWIPE_IN_OUT
(
EMPLOYEE_ID NUMBER(10) NOT NULL,
SWIPE_DATE DATE NOT NULL,
SWIPE_TIME DATE NOT NULL,
SWIPE_ID NUMBER(10) NOT NULL,
SWIPE_TYPE VARCHAR2(1 BYTE),
CREATED_BY NUMBER(10),
CREATION_DATE DATE,
LAST_UPDATED_BY NUMBER(10),
LAST_UPDATE_DATE DATE,
IS_MANUAL VARCHAR2(1 BYTE),
REASON_LKP NUMBER(10),
CLIENT_IP VARCHAR2(50 BYTE),
IS_REQUESTED VARCHAR2(1 CHAR),
TERMINAL_ID VARCHAR2(50 BYTE),
ATT_ID_REF NUMBER
)
CREATE TABLE CHR.CHR_EMGT_EMPLOYEE
(
EMPLOYEE_ID NUMBER(10) NOT NULL,
EMPLOYEE_CODE VARCHAR2(30 BYTE) NOT NULL
)
CREATE TABLE CHR.INOUT_LIVE_MACHINE_TEST
(
ATT_ID NUMBER,
USERID NUMBER,
EMPLOYEE_CODE NUMBER,
SENSORID NUMBER,
MACHINE_NUM VARCHAR2(20 BYTE),
CHECKTIME VARCHAR2(20 BYTE),
CHECKTYPE VARCHAR2(20 BYTE)
)
Your procedure has no mistakes. Only problem is in your table "INOUT_LIVE_MACHINE_TEST". it has missing SWIPE_DATE & SWIPE_TIME columns. See below the working demo.
Created table with both the columns:
CREATE TABLE INOUT_LIVE_MACHINE_TEST
(
ATT_ID NUMBER,
USERID NUMBER,
EMPLOYEE_CODE NUMBER,
SENSORID NUMBER,
SWIPE_DATE DATE NOT NULL,
SWIPE_TIME DATE NOT NULL,
MACHINE_NUM VARCHAR2(20 BYTE),
CHECKTIME VARCHAR2(20 BYTE),
CHECKTYPE VARCHAR2(20 BYTE)
)
Procedure compiled :
CREATE OR REPLACE PROCEDURE ATT_INSERT_TEST
IS
CURSOR ATT
IS
SELECT emp.EMPLOYEE_ID EMPLOYEE_ID,
io.CHECKTYPE CHECKTYPE,
io.MACHINE_NUM MACHINE_NUM,
io.ATT_ID ATT_ID,
io.SWIPE_DATE SWIPE_DATE,
io.SWIPE_TIME SWIPE_TIME
FROM INOUT_LIVE_MACHINE_TEST io, CHR_EMGT_EMPLOYEE emp
WHERE emp.EMPLOYEE_CODE = io.EMPLOYEE_CODE
AND io.ATT_ID NOT IN (SELECT ATT_ID_REF
FROM CHR_TA_EMP_SWIPE_IN_OUT
WHERE io.ATT_ID = ATT_ID_REF);
BEGIN
FOR I IN ATT
LOOP
INSERT INTO CHR_TA_EMP_SWIPE_IN_OUT (EMPLOYEE_ID,
SWIPE_DATE,
SWIPE_TIME,
SWIPE_ID,
SWIPE_TYPE,
CREATED_BY,
CREATION_DATE,
CLIENT_IP)
VALUES (I.EMPLOYEE_ID,
TO_DATE (i.SWIPE_DATE, 'MM/DD/YYYY'),
I.SWIPE_TIME,
CHR_TA_SWIPE_IN_OUT_SEQ.NEXTVAL,
I.CHECKTYPE,
I.EMPLOYEE_ID,
TO_DATE (i.SWIPE_DATE, 'MM/DD/YYYY'),
'192.168.0.71'
);
END LOOP;
COMMIT;
END;
/

PL/SQL Syntax problems

I am working on online platform to make an ERD and to get the PL/SQL code of it but I get the following code (see below) but I am not sure if it is PL/SQL.
I need to verify if this code is PL/SQL or not:
CREATE TABLE "CATEGORY" (
"ID" NUMBER(10) PRIMARY KEY,
"THLEVEL" NUMBER(10) NOT NULL
);
CREATE SEQUENCE "CATEGORY_SEQ" NOCACHE;
CREATE TRIGGER "CATEGORY_BI"
BEFORE INSERT ON "CATEGORY"
FOR EACH ROW
BEGIN
IF :NEW."ID" IS NULL THEN
SELECT "CATEGORY_SEQ".NEXTVAL INTO :NEW."ID" FROM DUAL;
END IF;
END;;
CREATE TABLE "REPORT" (
"ID" NUMBER(10) PRIMARY KEY,
"CLIENT" CLOB NOT NULL,
"VERSION" NUMBER(10) NOT NULL
);
CREATE SEQUENCE "REPORT_SEQ" NOCACHE;
CREATE TRIGGER "REPORT_BI"
BEFORE INSERT ON "REPORT"
FOR EACH ROW
BEGIN
IF :NEW."ID" IS NULL THEN
SELECT "REPORT_SEQ".NEXTVAL INTO :NEW."ID" FROM DUAL;
END IF;
END;;
CREATE TABLE "ASSET" (
"ID" NUMBER(10) PRIMARY KEY,
"REPORT" NUMBER(10) NOT NULL,
"IP" VARCHAR2(1000 CHAR) NOT NULL,
"NAME" VARCHAR2(1000 CHAR)
);
CREATE INDEX "IDX_ASSET__REPORT" ON "ASSET" ("REPORT");
ALTER TABLE "ASSET" ADD CONSTRAINT "FK_ASSET__REPORT" FOREIGN KEY ("REPORT") REFERENCES "REPORT" ("ID");
CREATE SEQUENCE "ASSET_SEQ" NOCACHE;
CREATE TRIGGER "ASSET_BI"
BEFORE INSERT ON "ASSET"
FOR EACH ROW
BEGIN
IF :NEW."ID" IS NULL THEN
SELECT "ASSET_SEQ".NEXTVAL INTO :NEW."ID" FROM DUAL;
END IF;
END;;
CREATE TABLE "SOLUTION" (
"ID" NUMBER(10) PRIMARY KEY,
"IMPLEVEL" VARCHAR2(1000 CHAR) NOT NULL,
"DIFFICULTY" VARCHAR2(1000 CHAR) NOT NULL,
"DESCRIPTION" CLOB NOT NULL
);
CREATE SEQUENCE "SOLUTION_SEQ" NOCACHE;
CREATE TRIGGER "SOLUTION_BI"
BEFORE INSERT ON "SOLUTION"
FOR EACH ROW
BEGIN
IF :NEW."ID" IS NULL THEN
SELECT "SOLUTION_SEQ".NEXTVAL INTO :NEW."ID" FROM DUAL;
END IF;
END;;
CREATE TABLE "VULNERABILITY" (
"ID" VARCHAR2(1000 CHAR) PRIMARY KEY,
"ASSET" NUMBER(10) NOT NULL,
"SOLUTION" NUMBER(10) NOT NULL,
"CATEGORY" NUMBER(10) NOT NULL,
"CVE" VARCHAR2(1000 CHAR),
"DATE" TIMESTAMP NOT NULL,
"LOCATION" CLOB NOT NULL
);
CREATE INDEX "IDX_VULNERABILITY__ASSET" ON "VULNERABILITY" ("ASSET");
CREATE INDEX "IDX_VULNERABILITY__CATEGORY" ON "VULNERABILITY" ("CATEGORY");
CREATE INDEX "IDX_VULNERABILITY__SOLUTION" ON "VULNERABILITY" ("SOLUTION");
ALTER TABLE "VULNERABILITY" ADD CONSTRAINT "FK_VULNERABILITY__ASSET" FOREIGN KEY ("ASSET") REFERENCES "ASSET" ("ID");
ALTER TABLE "VULNERABILITY" ADD CONSTRAINT "FK_VULNERABILITY__CATEGORY" FOREIGN KEY ("CATEGORY") REFERENCES "CATEGORY" ("ID");
ALTER TABLE "VULNERABILITY" ADD CONSTRAINT "FK_VULNERABILITY__SOLUTION" FOREIGN KEY ("SOLUTION") REFERENCES "SOLUTION" ("ID");
CREATE TABLE "EXPLOIT" (
"ID" NUMBER(10) PRIMARY KEY,
"VULNERABILITY" VARCHAR2(1000 CHAR) NOT NULL,
"NAME" VARCHAR2(1000 CHAR) NOT NULL,
"TYPE" CLOB NOT NULL,
"DESCRIPTION" CLOB NOT NULL
);
CREATE INDEX "IDX_EXPLOIT__VULNERABILITY" ON "EXPLOIT" ("VULNERABILITY");
ALTER TABLE "EXPLOIT" ADD CONSTRAINT "FK_EXPLOIT__VULNERABILITY" FOREIGN KEY ("VULNERABILITY") REFERENCES "VULNERABILITY" ("ID");
CREATE SEQUENCE "EXPLOIT_SEQ" NOCACHE;
CREATE TRIGGER "EXPLOIT_BI"
BEFORE INSERT ON "EXPLOIT"
FOR EACH ROW
BEGIN
IF :NEW."ID" IS NULL THEN
SELECT "EXPLOIT_SEQ".NEXTVAL INTO :NEW."ID" FROM DUAL;
END IF;
END;
So is this PL/SQL or is somethin else from Oracle? How this will sound in PL/SQL?
Well that is PL/SQL and it will work in Oracle if you remove the double semi-colon you have on create trigger.
https://dba.stackexchange.com/questions/1121/how-to-differentiate-between-sql-and-pl-sql
That is NOT PL/SQL. That is DDL (Data Definition Language). Specifically it is Oracle DDL.
These are DDL statements in which we can create, alter tables ,PL/SQL is a Procedural language SQL in which we use DML Statements for any Process.
These are a set of DDL commands and not PL/SQL as such. However if you incorporate these commands in a nice stored procedure or package, it might be termed as PL/SQL (procedural part of it) but not currently in its current shape.

How to increase the speed of table creation with index and constraints?

I have to create more than 500 tables having the same columns,indexes and constraints.
In The below code I have created table called TABLE_1 like wise i have to create tables from TABLE_1 to TABLE_500....
It takes more time for creating 500 tables and indexes.
Is there any way to increase speed of table creation.?
CREATE TABLE TABLE_1 (FEATURE_ID NUMBER(*,0) NOT NULL ENABLE,
COL_1 VARCHAR2(3 CHAR),
COL_2 VARCHAR2(5 CHAR),
COL_3 NUMBER(*,0),
COL_4 NUMBER(*,0),
COL_5 VARCHAR2(5 CHAR),
COL_6 CHAR(5 BYTE),
COL_7 NUMBER(*,0),
COL_8 VARCHAR2(50 CHAR),
COL_9 NUMBER(*,0),
COL_10 VARCHAR2(20 CHAR),
GEOMETRY SDO_GEOMETRY);
CREATE BITMAP INDEX TABLE_1_DM_IDX ON TABLE_1(COL_3);
CREATE BITMAP INDEX TABLE_1_ATR_IDX ON TABLE_1(COL_4);
CREATE INDEX TABLE_1_SPATIAL_IDX ON TABLE_1(GEOMETRY)
INDEXTYPE IS MDSYS.SPATIAL_INDEX;
ALTER TABLE TABLE_1 ADD CONSTRAINT TABLE_1_PK PRIMARY KEY (FEATURE_ID);
ALTER TABLE TABLE_1 ADD CONSTRAINT TABLE_1_PK PRIMARY KEY (FEATURE_ID);
Create a PLSQL script that creates the names for you.
begin
for i in 1..500 loop
execute immediate 'CREATE TABLE TABLE_'||i|| '
(FEATURE_ID NUMBER(*,0) NOT NULL ENABLE,
COL_1 VARCHAR2(3 CHAR),
COL_2 VARCHAR2(5 CHAR),
... ';
execute immediate 'CREATE BITMAP INDEX TABLE_'||i||'_DM_IDX ON TABLE_'||i||'(COL_3)';
... etc.
end loop;
end;
/

ORACLE IIF Statement

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.

Resources