Inserting clob-data into different table-columns - plsql

I have a table named 'uploaded_files' that stores *csv.files which are uploaded via dropzone (https://github.com/Dani3lSun/apex-plugin-dropzone) by a user in my webapplication. The content of that files is stored in a tablecolumn of datatype blob.
To insert the file-content I am using a package called 'csv_util_pkg' (https://github.com/mortenbra/alexandria-plsql-utils). I managed to convert the blob-datatype to clob-datatype and store the clob-data into another table called x_dump. X_Dump Table As you can see in the picture the clob_values are separated and stored in 'c001' and 'c002'. This is done by a function of the csv_util_pkg.
Now I want to take those two values and store them in a table called 'fahrzeug' but this doesn't work and I really don't know why. I am getting the following error code
ORA-01400: Einfügen von NULL in ("RESSOURCE_U"."FAHRZEUG"."VNUMMER") nicht möglich
ORA-06512: in Zeile 14
01400. 00000 - "cannot insert NULL into (%s)"
*Cause: An attempt was made to insert NULL into previously listed objects.
*Action: These objects cannot accept NULL values.
And here is my code:
DECLARE
file_content NUMBER (10);
l_clob CLOB;
BEGIN
SELECT TO_CLOB (
UTL_RAW.CAST_TO_VARCHAR2 (DBMS_LOB.SUBSTR (FILE_BLOB, 2000)))
INTO l_clob
FROM UPLOADED_FILES
WHERE UPLOADED_FILES.FILENAME LIKE 'A_%_Fahrzeug.csv';
INSERT INTO X_DUMP (CLOB_VALUE, DUMP_ID)
VALUES (l_clob, 1);
INSERT INTO fahrzeug (vnummer, baureihe)
SELECT c001, c002
FROM x_dump d, TABLE (csv_util_pkg.clob_to_csv (d.clob_value, ';'));
COMMIT;
END;
vnummer is the primary key of my table 'fahrzeug' and thus we can not insert null. But I don't understand that because c001 and c002 contain values so it can't be null..
Thanks for your help!

Did you debug or output the c001 during runtime? Try this:
for tmp IN (select c001 from x_dump d, table(csv_util_pkg.clob_to_csv(d.clob_value, ';')))
LOOP
DBMS_OUTPUT.put_line ('vnummer: ' || tmp.c001);
END LOOP;

Related

Stored Procedure returns "Error Code: 1054. Unknown column 'schema.table.col' in 'field list'" when Creating different temporary table on same session

When using a stored procedure to dynamically generate a table based on configuration and return a result set (SELECT) with the records in that table, the second call to that procedure to generate a different table structure returns no records and it reports a missing column from a previous temporary table of the same name.
I tried this with MariaDB 10.3 and 10.1.21 and received the same result. I have minimized my code here to the minimum to demonstrate the error after trying several variations of single and multiple sub-procedures.
I also tried using some transaction control with COMMITS after executing the process, before trying to start the process with a different parameter, but got the same results.
DROP PROCEDURE IF EXISTS CreateATable;
DELIMITER $$
CREATE PROCEDURE CreateATable( _TableType tinyint )
BEGIN
DROP TEMPORARY TABLE IF EXISTS aTable;
IF _TableType = 1 THEN
SET #SQL_Statement :=
CONCAT(
'CREATE TEMPORARY TABLE aTable (',
'the_id bigint, ',
'the_column varchar(100) ',
') engine=INNODB',
';');
ELSE
SET #SQL_Statement :=
CONCAT(
'CREATE TEMPORARY TABLE aTable (',
'the_id bigint, ',
'the_other_column varchar(100) ',
') engine=INNODB',
';');
END IF;
PREPARE stmtCreateTable FROM #SQL_Statement;
EXECUTE stmtCreateTable;
DEALLOCATE PREPARE stmtCreateTable;
SET #SQL_Statement := NULL;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS GetATable;
DELIMITER $$
CREATE PROCEDURE GetATable()
BEGIN
CALL CreateATable( 1 );
SELECT * FROM aTable;
CALL CreateATable( 2 );
SELECT * FROM aTable;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS GetATable2;
DELIMITER $$
CREATE PROCEDURE GetATable2(_TableType tinyint)
BEGIN
CALL CreateATable( _TableType );
SELECT * FROM aTable;
END$$
DELIMITER ;
/*
Test execution script starts here
*/
-- Just CALL Create for one and Select
CALL CreateATable( 1 );
DESCRIBE aTable;
SELECT * FROM aTable;
CALL CreateATable( 2 );
DESCRIBE aTable;
SELECT * FROM aTable;
-- -> no errors
-- now CALL procedure to Create and Select from two different temp tables
CALL GetATable();
-- -> no errors
-- now CALL procedure to CREATE AND SELECT from ONE temp table definition using a parameter to select
CALL GetATable2(1);
CALL GetATable2(2);
-- Error Code: 1054. Unknown column 'mySchema.aTable.the_column' in 'field list'
I would expect that I can pass a parameter to a stored procedure to generate a temporary table, and return the records of that temporary table. Even if I call that same procedure multiple times with different parameters on the same session.
The actual results are that when the stored procedure is called to generate the temporary table with a different table structure, it returns this error complaining about the column missing from the temporary table created in the previous invocation of that same stored procedure.
Error Code: 1054. Unknown column 'mySchema.aTable.the_column' in 'field list'
The only way I have found to prevent this error is
a. ending the jdbc connection and ending the server session
b. recompiling one of the stored procedures in the call stack
Recompiling is not viable. And ending the session seems unreasonable.
This seems like a defect. But would be interested to find if there is some way to get this to work.
This seems like a bug and you can report it directly to the MariaDB team at MariaDB bugs database.
A temporary solution is to use a prepared statement in the stored procedure GetATable2 (my test on MariaDB 10.3.16 to use EXECUTE IMMEDIATE):
...
CREATE PROCEDURE `GetATable2`(`_TableType` TINYINT)
BEGIN
CALL CreateATable(`_TableType`);
-- SELECT * FROM `aTable`;
EXECUTE IMMEDIATE 'SELECT * FROM `aTable`';
END$$
...
See dbfiddle.

how to use collection type in PLSQL, while receiving multiple value from front end java page?

Actually my requirement is,am having 3 tables so i need to create type for each table or consolidate type to all table. but in java developer have to send the multiple parameter to my Procedure, so how to get the multiple values in single type and insert it into table??
Object type
CREATE OR REPLACE TYPE "POL_QUAT_TYPE"
IS OBJECT (V_POLICY_NO VARCHAR2 (30),
V_FOREIGN_POLICY VARCHAR2 (1));
tabletype
CREATE OR REPLACE TYPE POL_QUAT_table IS TABLE OF POL_QUAT_TYPE
Sample procedure
CREATE OR REPLACE PROCEDURE TEST1 (A POL_QUAT_TYPE) IS
B VARCHAR2(100);
C VARCHAR2(100);
BEGIN
B:=A(1);
C:=A(1);
INSERT INTO TEST ( PART, B )
VALUES (B,C);
COMMIT;
END;
Call this procedure
begin
test1('a','b');
end;
I want to know how get the value (a,b) though procedure from collection type.
Ok, you can insert the contents of an array of objects into the table like so:
CREATE OR REPLACE TYPE "POL_QUAT_TYPE"
IS OBJECT (V_POLICY_NO VARCHAR2 (30),
V_FOREIGN_POLICY VARCHAR2 (1));
/
CREATE OR REPLACE TYPE POL_QUAT_table IS TABLE OF POL_QUAT_TYPE;
/
CREATE OR REPLACE PROCEDURE TEST1 (p_a in POL_QUAT_table)
as
BEGIN
INSERT INTO TEST (PART, B)
select t.v_policy_no,
t.v_foreign_policy
from table(p_a) t;
COMMIT;
END;
/
I've created a test case to demonstrate that it works over on Oracle LiveSQL.
This means you can insert all the content of the array in one go without having to loop through the array and insert one record at a time, so it should be much more performant.

How to use a bind variable in trigger body?

I'm new to PL/SQL. I'm using oracle 11g XE along with sql developer. I'm trying to create to create an after insert trigger as follows
create or replace trigger tr1
after
insert ON
employee
for each row
begin
print :new.emp_id;
end;
The employee table is as follows
create table employee
( emp_id varchar2(5) primary key,
emp_name varchar2(10),
salary number,
company varchar2(10) foreign key references companies(comp_name)
);
When I run the statement I got a 'enter binds' window for the bind variable :new. But I was confused that why do I need to enter the value for :new since it is pseudorecord. Then I entered 'employee' as the values for :new. Now I'm getting the following error.
Error(2,8): PLS-00103: Encountered the symbol "" when expecting one of the following: := . ( # % ; The symbol ":=" was substituted for "" to continue.
Your problem is not in the :new pseudorecord. The error is coming from the usage of print, which is used to print the bind variable used in successful PL/SQL block or used in an EXECUTE command. For example, you can use it this way:
VARIABLE n NUMBER
BEGIN
:n := 1;
END;
/
Then
PRINT n;
But if you want to test the value being inserted, you can use DBMS_OUTPUT.PUT_LINE like this:
create or replace trigger tr1
after
insert ON
employee
for each row
BEGIN
dbms_output.put_line(:new.emp_id);
END;
/
Enable DBMS_OUTPUT window in your SQL Developer, then run
insert into employee values(1, 'empName', 1000, 'ABC');
You'll see 1 printed out.
However, you can always test the value from the table. Because the value should be already inserted into table. You can just query.

Execute stored procedure error in select statement

I have a Procedure like this,
create or replace
PROCEDURE SP_PROOF
( proof_id IN NUMBER
, Type1 IN VARCHAR2
, StatementType IN NUMBER
, Resultset OUT NUMBER
) AS
BEGIN
IF StatementType = 1 Then
INSERT INTO ID_Proof (proofid,Id_type)
VALUES (proof_id, Type1);
ELSIF StatementType=2 THEN
SELECT proofid,Id_type Into Resultset FROM ID_Proof;
ELSIF StatementType=3 THEN
UPDATE ID_Proof SET Id_type = Type1 WHERE proofid = proof_id;
ELSIF StatementType=4 THEN
DELETE FROM ID_Proof WHERE proofid = proof_id;
end if;
end;
Im getting an error like this,
Error(14,1): PL/SQL: SQL Statement ignored
Error(14,64): PL/SQL: ORA-00947: not enough values
Please help me to correct the error.
Line 14 is:
SELECT proofid,Id_type Into Resultset FROM ID_Proof;
You are selecting two values, proofid and Id_type, into a single scalar variable Resultset. But you also have no filter, so even if you changed that to select a single value then you'd get a too-many-rows error if there was more than one row in the table (and no-data-found if the table is empty).
It isn't clear what you want to happen; perhaps you want select id_type into resultset from id_proof, but from the parameters id_type is a string - so selecting that into a number variable is likely to fail too. Or perhaps you want all IDs for the specified type, in which case the type of result set would need to be a table type or a ref cursor.
Having separate procedures and functions would be probably be clearer, too.

Insert and delete in oracle 11g procedure

I need to write a procedure with input parameters like groupid and item ids(array)
I need to insert into a table with values(groupid,itemid[0]) all items like (1,11),(1,12),(1,13),etc. I have table with two columns (groupid,itemid). please help me to sort out this problem. I am trying to write merge but getting error
CREATE OR REPLACE PROCEDURE update_product_group_prc
(
in_product_group_key IN INT,
in_product_key_array IN dbms_utility.maxname_array
)
AS
indx pls_integer := in_product_key_array.FIRST;
BEGIN
WHILE(INDX IS NOT NULL)
LOOP
MERGE INTO DIM_PRODUCT_X_GROUP PXG
USING(SELECT IN_PRODUCT_GROUP_KEY ,
IN_PRODUCT_KEY_ARRAY(INDX) IN_PRODUCT_KEY_ARRAY
FROM DUAL) IN_TBL
ON(IN_TBL.IN_PRODUCT_GROUP_KEY=PXG.PRODUCT_GROUP_KEY)
WHEN MATCHED THEN
-- DELETE --need to delete source records which r not here in array.
-- WHERE
WHEN NOT MATCHED THEN
INSERT (PRODUCT_GROUP_KEY,PRODUCT_KEY)
VALUES (IN_TBL.IN_PRODUCT_GROUP_KEY,IN_TBL.IN_PRODUCT_KEY_ARRAY);`
INDX := IN_PRODUCT_KEY_ARRAY.NEXT(INDX);
END LOOP;
END update_product_group_prc;
Error(16,41): PL/SQL: ORA-00936: missing expression
You have a syntax error. Comment the "WHEN MATCHED THEN" fragment.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm#SQLRF55028

Resources