Determining input datatype Oracle/PLSQL - oracle

I am writing a PLSQL 'INSTEAD OF INSERT' Trigger whereby the ID field (GID) can be inserted as either a string or a number. If the GID value is a string I would like to attempt to convert that into the correct GID (number) otherwise if a number is input the script will continue.
The part I am struggling with here is determining the datatype of ':New.CHART_GID' - is this possible in PLSQL? I can't check for chars in the string as the string may only contain numbers in some instances.
Thanks.

You can use TRANSLATE to check if there is something other as numbers:
CREATE OR REPLACE TRIGGER trigger_name
INSTEAD OF INSERT
ON table_name
FOR EACH ROW
DECLARE
vGID INTEGER;
...... other things
BEGIN
IF :New.CHART_GID is not null AND TRANSLATE(:New.CHART_GID,'0123456789',' ') is null THEN
vGID := TO_NUMBER(:New.CHART_GID);
.... do what you want with number
ELSE
... do what you want with not number
END IF;
.... other things
END;
CHART_GID have to be varchar2 in the view

I realise what I was trying to achieve was actually not possible. The solution for me was actually to join the Chart_no into the view and insert into either that field of the GID. If I input a Chart_no the GID field would be automatically populated and the same for if I input a GID.

Related

How to add values by using a sequence in plsql if only the field is null?

I need to add values for a number field and if only it is null, then I have to add a number by using a sequence. I have created the code for this. But since this field is a unique field
I can't add duplicate values. For example as the first record if I entered number 1 and in the next record if I not pass a value for that field, it will automatically generate a value and if its equals to a old record number its showing an error like record already exists. Can someone help me to solve this.
PROCEDURE InsertValues(
newrec_ IN OUT myTable%ROWTYPE,
indrec_ IN OUT Indicator_Rec,
attr_ IN OUT VARCHAR2 )
IS
BEGIN
IF(newrec_.id IS null) then
newrec_.id := myTable_id.NEXTVAL;
Client_SYS.Add_To_Attr('ID', newrec_.id, attr_);
END IF;
super(newrec_, indrec_, attr_);
END InsertValues;

How to implement multi value parameter in spagoBi server

I made a birt report in spagoBI studio with multi_value parameter it works fine in studio.
But when i upload it to server it's execution give a blank page.
pls someone help me.
Has been a couple of years since the queston was asked but I thought I would post my experience with this issue as it may help others out there.
The problem is due to the fact that each value in the parameter string is being wrapped with single quotes so no where condition is met in your report's sql where statement.
So if you are using Postgresql see: https://www.spagoworld.org/jforum/posts/list/382.page. However if like me you are using MySQL then that where all the fun and games begin because MySQL does not have a ready to use regxp_split_to_table function! What worked for me was to use temporary tables and a stored procedure to return the report dataset. I then called the procedure in the report's queryString.
So the following were the steps I took:
create a function to split out each parameter from the multivalue String and remove the single quotes:
CREATE DEFINER=root#localhost FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
) RETURNS varchar(255) CHARSET utf8
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '')
Create a stored procedure to return the parameters as a resultset that can be matched via your sql's where in ($P{parameter}) statement. Thet trick here is to take the split and cleaned up parameter and insert it into a temporary table that can then be queried in the subsequent select statement that returns the dataset. My stored procedure looks like:
CREATE DEFINER=root#localhost PROCEDURE create_temp_breweries(fullstr varchar(255), startDate date, endDate date, outlet_Type varchar(255))
BEGIN
DECLARE a INT Default 0 ;
DECLARE b INT Default 0 ;
DECLARE str VARCHAR(255);
DECLARE outletStr VARCHAR(255);
drop temporary table if exists temp_table1;
create temporary table temp_breweries(col1 varchar(255));
drop temporary table if exists temp_table2;
create temporary table temp_outletTypes(col2 varchar(255));
loop1: LOOP
SET a=a+1;
SET str= REPLACE(SPLIT_STR(fullstr,",",a),'\'', '');
IF str='' THEN
LEAVE loop1;
END IF;
#Do Inserts into temp table here with str going into the row
insert into temp_table1 values (str);
END LOOP loop1;
loop2: LOOP
SET b=b+1;
SET outletStr= REPLACE(SPLIT_STR(outlet_Type,",",b),'\'', '');
IF outletStr='' THEN
LEAVE loop2;
END IF;
#Do Inserts into temp table here with outletStr going into the row
insert into temp_table2 values (outletStr);
# For testing: insert into mytest (brewery) values (outletStr);
END LOOP loop2;
SELECT [fields]
FROM
[tables]
WHERE
BINARY field IN (SELECT * FROM temp_table1)
AND DATE BETWEEN startDate AND endDate AND
BINARY field2 IN (SELECT * FROM temp_table2);
END
Got this from: MySQL Split Comma Separated String Into Temp Table.
I am sure there must be a better or easier way but this worked like a charm!

Binding Variables in PL/SQL

I read this script that assigns of a data column info into 2 binding variables.
something like this:
EXEC SQL SELECT
var1
into :v.v1:v2
from table
Shouldn't there be a comma in there? Or is this like assigning var1 into v.v1 and also into v2 with the same values?
The above script would give error only. if you want to assign value comma is required for the same.
The syntax would be :- Ex if you want to fetch Empno,Ename,Deptno,salary from
EMPLOYEES.The plsql block would be as given below.
DECLARE
L_EMPNO NUMBER;
L_ENAME VARCHAR2(1000);
L_DEPTNO NUMBER;
L_SALARY NUMBER;
BEGIN
SELECT EMPNO, ENAME, DEPTNO, SALARY
INTO L_EMPNO, L_ENAME, L_DEPTNO, L_SALARY
FROM EMPLOYEES
WHERE EMPNO=100;
END;
This code is a snippet from a PRO*C program, a C program with embedded SQL.
v2 is an indicator variable. See here for info: https://docs.oracle.com/cd/B28359_01/appdev.111/b28427/pc_04dat.htm#i12463
An indicator variable will contain a value that relates to it's associated variable which in this case is v.v1 and is set after the operation in which it is used. In this case, after the select, you can test v2 and based on it's value it will tell you info about v.v1:
From the link above, if v2 equals:
0 - The operation was successful
-1 - A NULL was returned, inserted, or updated.
-2 - Output to a character host variable from a "long" type was truncated, but the original column length cannot be determined.
>0 - The result of a SELECT or FETCH into a character host variable was truncated. In this case, if the host variable is a multibyte character variable, the indicator value is the original column length in characters. If the host variable is not a multibye character variable, then the indicator length is the original column length in bytes.
I would suggest using it's other form, which would make things clear for the person that will maintain this after you (at least do that person a favor and comment this when you get your head around it). Always code for the person that will maintain after you. Don't you wish the person before you did that?!:
EXEC SQL SELECT
var1
into :v.v1 INDICATOR :v2
from table

Reading IN parameters in a query in PL/SQL

I have written a PL/SQL procedure as:
CREATE OR REPLACE PROCEDURE checkProdQuantity (productid IN number, orderqty IN number)
IS
qty number;
qty_diff number;
BEGIN
SELECT quantity INTO qty from Products where ProductID=productid;
IF orderqty>qty THEN
dbms_output.put_line('Ordered quatity is greater than available quantity');
ELSE
qty_diff:=qty-orderqty;
UPDATE Products set quantity=qty_diff where ProductID=productid;
END IF;
END;
/
But when I try to execute this procedure with valid parameters, it shows an error: exact fetch returns more than the requested number of rows.
I have checked my table, and for the parameters I am supplying it should return only one row. I think for some reason, the value of productid IN parameter is not being read in the select query. Even if I provide some random values for productid parameter, it still gives the same error. I am unable to figure out where the problem is.
I don't think the compiler is distinguishing between the parameter productid and the column name ProductID.
Try renaming your parameter to a_productId, or something different from the column name.
Its happning because, when you write
SELECT quantity INTO qty from Products where ProductID=productid;
Oracle scope resolution interprets productid as the column_name and not as your input variable.
Change the name of the input variable to something other than the column name and it should work.
Hope it helps
Vishad

Generate automatic Id

I am making a web application which uses a database in which I have a field I_ID which i want to automatically increment like I0 then I1 then I2 and so on with each record insertion in the database.
To achieve it I made a trigger for this table.But its not working fine.What can be the reason.Please help
My Trigger T1:
CREATE OR REPLACE TRIGGER "T1"
before
insert on "TBINDIVIDUAL"
for each row
declare
x varchar2(10);
mx varchar2(13);
mx2 varchar2(13);
y number(3);
begin
x:=:new.I_ID;
mx:=substr(x,1,1);
select max(I_ID) into mx2 from tbindividual where I_ID like mx||'%';
y:=to_number(substr(mx2,2));
:new.I_ID:=mx||to_char(y+1);
end t1;
/
EDITED :
As i do by answer
CREATE OR REPLACE TRIGGER "TBINDIVIDUAL_T1"
BEFORE
insert on "TBINDIVIDUAL"
for each row
begin
:new.I_ID = SEQ1.nextval;
end;
/
But it give two errors
Encountered the symbol "=" when expecting one of the following: := . ( # % ; indicator
Encountered the symbol "END"
Please help
So Oracle is not SQL Server...
if you want to get unique ID's, you need to populate them from a sequence.
for creating a sequence use:
create sequence myseq;
and in your code use (depends on the version):
:new.I_ID := myseq.nextval;
or
select myseq.nextval into :new.I_ID from dual;
the problem your code doesn't work is what :new and :old means...
I would recommend you reading about their meaning...
Hope I've been helpful...
Because of the discussion in the comments - here is a full example:
for this table:
CREATE TABLE test (A number);
to add a unique, sequential ID you need to first create a sequence:
CREATE SEQUENCE myseq;
and a trigger:
CREATE OR REPLACE TRIGGER "T1"
before
insert on "test"
for each row
begin
:new.I_ID := myseq.nextval;
end t1;
/
by the way - I would recommend to check before substituting :new.I_ID, if it is null or not, cause sometimes in upgrades people add a unique ID from an external resource.. (such as them getting a unique number from the sequence themselves...)
you can read more about sequences here:
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6015.htm#SQLRF01314
sorry for the way the code is displayed.. need to learn how to write code here...
One more thing - In Oracle - you cannot create such a PL/SQL to increase existing counter without locks.
Concurrent queries might run the first query in the PL/SQL simultaneously, which means multiple sessions will get the same I_ID.
Also notice that in your code you queried the max on varchar, which is not the same as max on number...
Adding concatenated text is unrelated to the unique ID. In your case it will look like:
:new.I_ID = substr(:new.I_ID,1,1)||to_char(myseq.nextval);
assuming x is being inputted with the char you want..

Resources