If statement inside create table query -Oracle- - oracle

I would like to create table which asks user input first. Then based on the input, it select which columns are added.
for example, if the response is 'N', then table is created including columns col1, col2, col3.
If the response is 'Y', table is created including columns col1, col2, col3, col4, col5.
Is this possible?
If yes, please provide me simple and primitive query so that I can apply it to my case.
Thanks,

Using SQL*Plus it's simple:
ACCEPT table_option -
PROMPT 'Create more columns? '
SET TERM OFF
COLUMN extra_columns NEW_VALUE extra_columns
SELECT
CASE '&table_option'
WHEN 'Y' THEN ', C4 NUMBER, C5 VARCHAR2(255), C6 DATE'
END extra_columns FROM DUAL;
CREATE TABLE tmp (
C1 NUMBER,
C2 VARCHAR2(255),
C3 DATE &extra_columns
);
SET TERM ON
You can store the script as a file and invoke it from SQL*Plus using #filename.

CREATE OR REPLACE FUNCTION tmp_custom_DDL( p_input VARCHAR2 IN, p_resp CHAR IN OUT) RETURN CHAR
AS
v_str VARCHAR2(4000);
IF p_resp = 'Y' THEN
v_str := 'col1 varchar2(10), col2 varchar2(10), col3 varchar2(10)';
ELSE v_str := 'col1 varchar2(10), col2 varchar2(10), col3 varchar2(10), col4 varchar2(10), col4 varchar2(10) ' ;
EXECUTE IMMEDIATE v_comm_1 || v_str || v_comm2;
--v_comm_1 is the first half of create table command till the specified cols
--v_comm_2 is the rest of the create table command
RETURN p_resp;
END;
this is only a quick draft, fix the few lexical bug and the missing definitions :) (this is the first step)

Related

Oracle-Using optional prameters in function?

I want to add at most three optional parameters to my Oracle function named TEST.
Returned value should be 2.
How to modify my function to make these queries work in a simplest way?
SELECT TEST('eq1','md1') TEST0 FROM DUAL; -- Shows 2 correctly
--How to make these queries also work?
SELECT TEST('eq1','md1','c1') TEST1 FROM DUAL;
SELECT TEST('eq1','md1','c1','d1') TEST2 FROM DUAL;
SELECT TEST('eq1','md1','c1','d1','e1') TEST3 FROM DUAL;
Table and Function are as below.
Table as below
CREATE TABLE T5 (
COL1 VARCHAR2(10),
COL2 VARCHAR2(10),
COL3 VARCHAR2(10),
COL4 VARCHAR2(10),
COL5 VARCHAR2(10),
VAL VARCHAR2(10)
);
INSERT INTO T5 VALUES ('eq1','md1','c1','d1','e1','2');
INSERT INTO T5 VALUES ('eq2','md2','c2','d2','e2','5');
INSERT INTO T5 VALUES ('eq3','md3','c3','d3','e3','3');
My funtion is,
CREATE OR REPLACE FUNCTION TEST
(p1 IN VARCHAR2,
p2 IN VARCHAR2
--How to add optional parameter p3?
--How to add optional parameter p4?
--How to add optional parameter p5?
)
RETURN NUMBER AS V_VALUE VARCHAR2(10);
BEGIN
SELECT(
SELECT VAL FROM T5
WHERE COL1 = p1
AND COL2 = p2
--How to add constraint COL3=p3?
--How to add constraint COL4=p4?
--How to add constraint COL5=p5?
)
INTO V_VALUE
FROM DUAL;
RETURN V_VALUE;
END;
/
You need to define the default value and that's it.
Your function code should look like as follows:
CREATE OR REPLACE FUNCTION TEST (
P1 IN VARCHAR2,
P2 IN VARCHAR2,
P3 IN VARCHAR2 DEFAULT NULL,
P4 IN VARCHAR2 DEFAULT NULL,
P5 IN VARCHAR2 DEFAULT NULL
) RETURN NUMBER AS
V_VALUE VARCHAR2(10);
BEGIN
SELECT
(
SELECT
VAL
FROM
T5
WHERE
COL1 = P1
AND COL2 = P2
AND COL3 = COALESCE(P3, COL3)
AND COL4 = COALESCE(P4, COL4)
AND COL5 = COALESCE(P5, COL5)
)
INTO V_VALUE
FROM
DUAL;
RETURN V_VALUE;
END TEST;
/
Now, all the queries will run:
SELECT TEST('eq1','md1') TEST0 FROM DUAL;
SELECT TEST('eq1','md1','c1') TEST1 FROM DUAL;
SELECT TEST('eq1','md1','c1','d1') TEST2 FROM DUAL;
SELECT TEST('eq1','md1','c1','d1','e1') TEST3 FROM DUAL;
But, Please make sure that order of the passed parameter in the function is not broken.
You can not pass the P5 without passing P4 parameter value except the parameter names are used while calling the function.
Cheers!!

Need assistance in creating a procedure to load the data into CSV file using plsql

I have a three tables as below.
Create table t1_Fact ( Cur_date Date, Name varchar2(10), Event varchar2(50), Price Number(10,0), TAX Number(10,0), Flag Number );
Create table App_Fact ( Application_ID Number, Application_Name varchar2(100), Application_Price Number, Appliation_Tax Number, Flag Number );
Create table t2 ( Table_Name Varchar2(100), Table_Columns Varchar(100), Table_Measure varchar2(100), t3_columns varchar2(100), t3_measures varchar2(100), t3_Where_Clause varchar2(100) );
Create table t3 ( Cur_date Date, Name varchar2(10), Event varchar2(50), Application_ID Number, Application_Name varchar2(100), Application_Price Number, Appliation_Tax Number, Price Number(10,0), TAX Number(10,0), Flag Number );
table t2 contains all the table names,column names of each source and destination tables and where clause conditions.
[t2 Details][1]
Here I need to insert the data from t3 to particular fact table by using group by the column names of fact table, measures and where clause by passing the fact table name as parameter.
Like if we pass t1_Fact table in procedure, we must get all the details from t2 and get the details from t3 and insert into t1_Fact and also save them into CSV file
I have tried the following procedure however I'm not able to insert the data into csv file
Create or Replace Procedure CommonProcedure(sourceTableName IN VARCHAR2) Is
tablename t2.Table_Name%TYPE;
destcolumns t2.Table_Columns%TYPE;
destMeasures t2.Table_Measure%TYPE;
whereClause t2.t3_Where_Clause%TYPE;
sourceColumns t2.t3_columns%TYPE;
sourceMeasures t2.t3_measures%TYPE;
q1 VARCHAR2(3000 BYTE);
pathInfo VARCHAR2(3000 BYTE);
v_file UTL_FILE.FILE_TYPE;
Cursor TableName Is SELECT Table_Name FROM t2;
Begin
--Path will be getting from another table using the function in the format of '/data/Oracle-files/Table_CSV'
pathInfo := getDBConfigParamValue('FILE_LOCATION');
Open c1;
Loop
Fetch TableName Into tablename;
Exit When TableName%notfound;
SELECT Table_Columns, Table_Measure, t3_columns, t3_measures INTO destcolumns,destMeasures,sourceColumns,sourceMeasures FROM t2 where Table_Name = tablename;
q1 := 'INSERT INTO '||tablename||'('||destColumns||','||destMeasures||')'||
' ( SELECT '||sourceColumns||','||sourceMeasures||','||sourceTableName
||' FROM '||sourceTableName||' GROUP BY '||sourceColumns||')';
Execute Immediate q1;
--Need to load the data into tablename.CSV
v_file := UTL_FILE.FOPEN('' || pathInfo ||',' ||destinationTableName ||'.csv' || '','W');
UTL_FILE.PUT_LINE(v_file,'' ||destColumns ||',' ||destMeasures ||'');
UTL_FILE.FCLOSE(v_file);
End Loop;
Close TableName;
End;
When I compile the above procedure getting following error
LINE/COL ERROR
-------- -----------------------------------------------------------------
47/13 PL/SQL: Statement ignored
47/23 PLS-00306: wrong number or types of arguments in call to 'FOPEN'
Please assist me further.
Thanks in advance.
PLS-00306: wrong number or types of arguments in call to 'FOPEN'
Your fopen call is only passing two arguments; you are concatenating a comma into the first value, rather than using it as an argument separator, so you are passing the constructed string '<pathInfo>,<destinationTableName>.csv' as the location, 'W' as the filename, and no third argument for the open mode.
You can see the problem if I highlight it:
v_file := UTL_FILE.FOPEN('' || pathInfo ||',' ||destinationTableName ||'.csv' || '','W');
^^^^^^^^
Continuing your pattern of concatenating empty strings (?) you have it the wrong side of a closing quote:
v_file := UTL_FILE.FOPEN('' || pathInfo ||'', destinationTableName ||'.csv' || '','W');
or maybe even:
v_file := UTL_FILE.FOPEN('' || pathInfo ||'', '' || destinationTableName ||'.csv' || '','W');
but you don't need to do all that confusing concatenation, you can just do:
v_file := UTL_FILE.FOPEN(pathInfo, destinationTableName ||'.csv', 'W');

ORA-00928: missing SELECT keyword

In MYTABLE there are courses and their predecessor courses.
What I am trying to is to find the courses to be taken after the specified course. I am getting missing SELECT keyword error. Why I am getting this error although I have SELECT statement in FOR statement ? Where am I doing wrong ?
DECLARE
coursename varchar2(200) := 'COURSE_101';
str varchar2(200);
BEGIN
WITH DATA AS
(select (select course_name
from MYTABLE
WHERE predecessors like ('''%' || coursename||'%''')
) str
from dual
)
FOR cursor1 IN (SELECT str FROM DATA)
LOOP
DBMS_OUTPUT.PUT_LINE(cursor1);
END LOOP;
end;
Unless I'm wrong, WITH factoring clause can't be used that way; you'll have to use it as an inline view, such as this:
declare
coursename varchar2(200) := 'COURSE_101';
str varchar2(200);
begin
for cursor1 in (select str
from (select (select course_name
from mytable
where predecessors like '''%' || coursename||'%'''
) str
from dual
)
)
loop
dbms_output.put_line(cursor1.str);
end loop;
end;
/
Apart from the fact that it doesn't work (wrong LIKE condition), you OVERcomplicated it. This is how it, actually, does something:
SQL> create table mytable(course_name varchar2(20),
2 predecessors varchar2(20));
Table created.
SQL> insert into mytable values ('COURSE_101', 'COURSE_101');
1 row created.
SQL>
SQL> declare
2 coursename varchar2(20) := 'COURSE_101';
3 begin
4 for cursor1 in (select course_name str
5 from mytable
6 where predecessors like '%' || coursename || '%'
7 )
8 loop
9 dbms_output.put_line(cursor1.str);
10 end loop;
11 end;
12 /
COURSE_101
PL/SQL procedure successfully completed.
SQL>
Also, is that WHERE clause correct? PREDECESSORS LIKE COURSENAME? I'm not saying that it is wrong, just looks somewhat strange.
To extend #Littlefoot's answer a bit: you can use a common table expression (WITH clause) in your cursor, but the WITH must be part of the cursor SELECT statement, not separate from it:
DECLARE
coursename varchar2(200) := 'COURSE_101';
BEGIN
FOR aRow IN (WITH DATA AS (select course_name AS str
from MYTABLE
WHERE predecessors like '''%' || coursename||'%''')
SELECT str FROM DATA)
LOOP
DBMS_OUTPUT.PUT_LINE(aRow.str);
END LOOP;
END;
Also note that the iteration variable in a cursor FOR-loop represents a row returned by the cursor's SELECT statement, so if you want to display whatever was returned by the cursor you must use dotted-variable notation (e.g. aRow.str) to extract fields from the row.
Best of luck.
CREATE TABLE product
(
PRODUCT_ID int Primary key,
NAME VARCHAR (20) not null,
Batchno int not null,
Rate int not null,
Tax int not null,
Expiredate date not null
);
INSERT INTO PRODUCT VALUSES(1 , 'vasocare', 32 , 15 , 2 , 01-JAN-2021);

Oracle - Cannot update table record using bind variable

This query returns 1 row:
SELECT col1, col2 FROM table1 WHERE col1 = :column1;
But this updates 0 rows:
UPDATE table1 SET col2 = :column2 WHERE col1 = :column1;
COMMIT;
I added this constraint to set col1 as primary key, but it didn't fix it.
ALTER TABLE table1 ADD CONSTRAINT col1_pk PRIMARY KEY (col1);
I am trying this from SQL Developer, any idea why it does not update the row?
EDIT:
col1 is VARCHAR2(32 BYTE) NOT NULL
col2 is CLOB NOT NULL
EDIT 2: Test Case, set :var1 to 0011223344556677 in the select and update sentences.
CREATE TABLE MY_TABLE
( COL1 VARCHAR2(32 BYTE) NOT NULL ENABLE,
COL2 CLOB,
CONSTRAINT "MY_TABLE_PK" PRIMARY KEY ("COL1")
)
INSERT INTO MY_TABLE (COL1, COL2) VALUES ('0011223344556677', '1434407992143440799214344079921434407992');
SELECT * FROM MY_TABLE WHERE COL1 = :var1;
UPDATE MY_TABLE SET COL2 = 'test' WHERE COL1 = :var1;
COMMIT;
TL;DR - Make sure the value being stored in the bind variable is parsed as a character string not a number.
I've run this in SQL Developer (Version 4.0.3.16):
CREATE TABLE MY_TABLE
( COL1 VARCHAR2(32 BYTE) NOT NULL ENABLE,
COL2 CLOB,
CONSTRAINT "MY_TABLE_PK" PRIMARY KEY ("COL1")
);
/
INSERT INTO MY_TABLE (COL1, COL2) VALUES ('0011223344556677', '1434407992143440799214344079921434407992');
/
VARIABLE var1 VARCHAR2(32);
/
BEGIN
:var1 := '0011223344556677';
END;
/
SELECT * FROM MY_TABLE WHERE COL1 = :var1;
/
UPDATE MY_TABLE SET COL2 = 'test' WHERE COL1 = :var1;
/
COMMIT;
/
SELECT * FROM MY_TABLE;
/
And it runs fine:
table MY_TABLE created.
1 rows inserted.
anonymous block completed
COL1 COL2
-------------------------------- --------------------------------------------------------------------------------
0011223344556677 1434407992143440799214344079921434407992
1 rows updated.
committed.
COL1 COL2
-------------------------------- --------------------------------------------------------------------------------
0011223344556677 test
If you change the variable assignment to (remove quotes):
BEGIN
:var1 := 0011223344556677;
END;
Then the value is parsed as a number and the leading zeros are ignored and the output is:
table MY_TABLE created.
1 rows inserted.
anonymous block completed
no rows selected
0 rows updated.
committed.
COL1 COL2
-------------------------------- --------------------------------------------------------------------------------
0011223344556677 1434407992143440799214344079921434407992

Select List of Column Names / Aliases from Custom Sub-Query

In Oracle, is there a way to select all the columns that are returned from a custom query with aliases? As an example, let's say we have a query as the following:
SELECT FIRST_NAME AS COL1, LAST_NAME AS COL2, ADDRESS AS COL3
FROM PEOPLE
I would like to know if an encapsulating query can be made that would return:
COL1
COL2
COL3
Here is how to do it in PL/SQL. Don't know if it is possible with straight oracle SQL only. You could always encapulate it in some kind of function if needed.
DECLARE
TYPE RefCursor_Type IS REF CURSOR;
D_RefCur RefCursor_Type;
D_DescriptionTable DBMS_SQL.DESC_TAB2;
D_ColumnCount INTEGER;
D_CursorHandle INTEGER;
BEGIN
OPEN D_RefCur
FOR 'SELECT FIRST_NAME AS COL1, LAST_NAME AS COL2, ADDRESS AS COL3 FROM PEOPLE';
D_CursorHandle := DBMS_SQL.to_cursor_number (D_RefCur);
DBMS_SQL.DESCRIBE_COLUMNS2 (D_CursorHandle,
D_ColumnCount,
D_DescriptionTable);
FOR idx IN 1 .. D_ColumnCount
LOOP
DBMS_OUTPUT.put_line (D_DescriptionTable (idx).col_name);
END LOOP;
END;

Resources