Datagrip removed some variable inside procedure - datagrip

I'm using DataGrip v 219.1.4. I created this procedure:
CREATE
PROCEDURE SP_Add_Edit_Credit_Expiration
(IN _ID bigint, IN _User_Id bigint UNSIGNED,
IN _Value decimal(16, 3),
IN _Factor_Id bigint UNSIGNED,
IN _Prefactor_id bigint UNSIGNED,
IN _Expired_At timestamp,
IN _Description varchar(255))
BEGIN
IF (ISNULL(_User_Id))
THEN
SET _User_Id = #Auth_User;
END IF;
IF _ID
THEN
UPDATE Tb_Credit_Expirations SET value=IFNULL(_Value, value) WHERE id = _ID;
ELSE
INSERT INTO Tb_Credit_Expirations
SET value=_Value,
user_id = _User_Id,
factor_id=_Factor_Id,
prefactor_id=_Prefactor_id,
expired_at=_Expired_At,
description=_Description,
created_at = CURRENT_TIMESTAMP;
SET _ID = LAST_INSERT_ID();
END IF;
END;
But when I want to see it :
CREATE PROCEDURE SP_Add_Edit_Credit_Expiration
(IN _ID bigint,
IN _User_Id bigint UNSIGNED,
IN _Value decimal(16, 3),
IN _Factor_Id bigint UNSIGNED,
IN _Prefactor_id bigint UNSIGNED,
IN _Expired_At timestamp,
IN _Description varchar(255))
BEGIN
IF (ISNULL())
THEN
SET = #Auth_User;
END IF;
IF
THEN
UPDATE Tb_Credit_Expirations SET value=IFNULL(, value) WHERE id = ;
ELSE
INSERT INTO Tb_Credit_Expirations
SET value=,
user_id = ,
factor_id=,
prefactor_id=,
expired_at=,
description=,
created_at = CURRENT_TIMESTAMP;
SET = LAST_INSERT_ID();
END IF;
END;
all IN variables removed inside procedure. But the procedure work fine inside my php code!
more than one my procedures it happened. I removed it and make it again but I see an incomplete procedure!
On mysql workbench software show me a complete procedure.

Related

Invalid reference in Oracle database

I am using Oracle database 19c for a project. I have created the alumni table as shown below:
CREATE TABLE Alumni (
ID NUMBER GENERATED ALWAYS AS IDENTITY ,
First_Name varchar2(20) NOT NULL,
Last_Name varchar2(20) NOT NULL,
Gender char(1) NOT NULL,
CHECK (Gender IN('M','F')),
Graduation_Year number NOT NULL,
check (Graduation_Year>=1980 AND Graduation_Year<=2020),
Degree_Course varchar2(255) not null,
Award_Nominated CHAR(1),
CHECK (Award_Nominated IN('Y','N')),
Award_Won CHAR(1),
CHECK (Award_Won IN('Y','N')),
Phone_Number VARCHAR2(15) not null,
Email_Address VARCHAR2(255) not null,
CONSTRAINT ALUM_PK PRIMARY KEY(ID)
);
Then I tried to define a function that will allow me to search by First or last name in a section of the table, shown below:
CREATE OR REPLACE TYPE alum_row_type is object(ID number,First_name varchar2(20),Last_Name
varchar2(20),Phone_number varchar2(15),Email_Address varchar2(255));
CREATE OR REPLACE TYPE t_alum_row_type as table of alum_row_type;
CREATE OR REPLACE FUNCTION Name_Search RETURN t_alum_row_type
IS
L_alum_row t_alum_row_type := t_alum_row_type();
X integer :=0;
BEGIN
FOR R IN (SELECT ID,First_Name, Last_Name,Phone_Number,Email_Address FROM alumni)
LOOP
L_alum_row.extend;
X:=X+1;
L_alum_row(X):= alum_row_type(X.ID,X.First_Name, X.Last_Name, X.Phone_Number, X.Email_Address);
END LOOP;
RETURN L_alum_row;
END;
After running this, I get this error:
LINE/COL ERROR
--------- -------------------------------------------------------------
10/9 PL/SQL: Statement ignored
10/41 PLS-00487: Invalid reference to variable 'X'
Errors: check compiler log
How can I resolve this issue. I am relatively new to PL\SQL, so please explain it simply.
This is not possible
L_alum_row(X):= alum_row_type(X.ID,X.First_Name, X.Last_Name, X.Phone_Number, X.Email_Address);
You are referencing X.ID, X.Phone_Number etc. . . but declared X as an integer. If you are trying to access the current loop record, try with
L_alum_row(X):= alum_row_type(R.ID,R.First_Name, R.Last_Name, R.Phone_Number, R.Email_Address);
As you declared the loop iterator as R for your cursor
FOR R IN (SELECT ID,First_Name, Last_Name,Phone_Number,Email_Address FROM alumni)
You can eliminate the loop altogether by using BULK COLLECT. Thereby reducing the function to basically a single select statement.
function name_search
return t_alum_row_type
is
l_alum_row t_alum_row_type := t_alum_row_type();
begin
select alum_row_type(id,first_name, last_name,phone_number,email_address)
bulk collect
into l_alum_row
from alumni;
return l_alum_row;
end;

“How to fix trigger in oracle pl/sql?

Problem:
Need a TRIGGER for the Table A which does the following:
Each time an INSERT is made into Table A on column TRT_PROCEDURE value, add 1
to the column 'TRT_INS_COUNT' in the table B. If the TRT_PROCEDURE value does
not exist in the table B, add a row to the table B for the procedure setting
TRT_INS_COUNT to 1.
Each time a DELETE is made on Table A, add 1 to the column TRT_DEL_COUNT in
table B for that Procedure value if it exists in the table B. If it does not
exist in the table B, add a row to the table B for the procedure and set
TRT_DEL_COUNT to 1.
Each time an UPDATE occurs for Column TRT_PROCEDURE in TABLE A, add 1 to the
column TRT_UPD_COUNT in table B. If it is not in the table B, add a row to
the table B for the procedure value and set TRT_UPD_COUNT to 1. If the Column
TRT_PROCEDURE value in TABLE A is changed, add 1 to the TRT_UPD_COUNT for the
old procedure value.
Test by doing several INSERTs, DELETEs, and UPDATEs and then display the table B.
Updates: whenever an value of trt_procedure is inserted into table B, the second same trt_procedure (e.g '88-20') cannot be correctly counted into its designated count field. Not sure where went wrong.
TABLE A
Name Null Type
TRT_ID NOT NULL NUMBER(3)
PAT_NBR NUMBER(4)
PHYS_ID NUMBER(3)
TRT_PROCEDURE VARCHAR2(5)
TRT_DATE DATE
TABLE B
Name Null Type
TRT_PROCEDURE NOT NULL VARCHAR2(5)
TRT_INS_COUNT NUMBER(3)
TRT_DEL_COUNT NUMBER(3)
TRT_UPD_COUNT NUMBER(3)
TEST SAMPLES
INSERT INTO A VALUES (11, 8031,101,'88-20',sysdate );
INSERT INTO A VALUES (12, 5872,101,'60-00',sysdate );
UPDATE A SET trt_procedure = '88-20' WHERE trt_id=6;
/*row trt_id =6 cloumn trt_procedure old value '54-60'
new value '88-20', which means Table B row '88-20' and
row '54-60 both trt_upd_count should add 1*/
DELETE FROM A WHERE trt_id=1;
/*row trt_id =1 cloumn trt_procedure value also '88-20', which means
that Table B row '88-20' trt_del_count should also add 1*/
CREATE OR REPLACE TRIGGER trt_stats_trg
BEFORE INSERT OR UPDATE OR DELETE OF TRT_procedure ON A FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE B SET trt_ins_count = trt_ins_count+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_ins_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF UPDATING THEN
UPDATE B SET trt_upd_count = trt_upd_count+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:old.trt_procedure, 1);
END IF;
UPDATE B SET trt_upd_count = trt_upd_count+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF DELETING THEN
UPDATE B SET trt_del_count = trt_del_count+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_del_count)
VALUES (:old.trt_procedure, 1);
END IF;
END IF;
END trt_stats_trg;
Here you go, with a few fixes.
The tables:
create table a(
TRT_ID NUMBER(3) NOT NULL ,
PAT_NBR NUMBER(4),
PHYS_ID NUMBER(3),
TRT_PROCEDURE VARCHAR2(5),
TRT_DATE DATE
);
create table b(
TRT_PROCEDURE VARCHAR2(5) NOT NULL,
TRT_INS_COUNT NUMBER(3),
TRT_DEL_COUNT NUMBER(3),
TRT_UPD_COUNT NUMBER(3)
);
And the trigger
CREATE OR REPLACE TRIGGER trt_stats_trg
BEFORE INSERT OR UPDATE OR DELETE ON A FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE B SET trt_ins_count = nvl(trt_ins_count,0)+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_ins_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF UPDATING('TRT_PROCEDURE') THEN
if nvl(:old.trt_procedure, 'X') <> nvl(:new.trt_procedure, 'X') then
UPDATE B SET trt_upd_count = nvl(trt_upd_count,0)+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:old.trt_procedure, 1);
END IF;
UPDATE B SET trt_upd_count = nvl(trt_upd_count,0)+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:new.trt_procedure, 1);
END IF;
end if;
ELSIF DELETING THEN
UPDATE B SET trt_del_count = nvl(trt_del_count, 0)+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_del_count)
VALUES (:old.trt_procedure, 1);
END IF;
END IF;
END trt_stats_trg;
/
Key points:
You can use UPDATING('COLUMN_NAME') to detect when the SQL affects a specific column.
When UPDATING, you may wish to check for non-changing updates, where a column with value "ABC" is being updated to "ABC". This often happens in frameworks that simply include all columns in an update even when they are not really changing. Detect this with something similar to if nvl(:old.trt_procedure, 'X') <> nvl(:new.trt_procedure, 'X') then.
Table B does not have default values for the counts, so when the original trigger tried to update table B, it succeeded...in updating NULL to NULL, as that's what happens when you add 1 to NULL. This can be addressed by either assigning a default value of 0 to the columns in the table or by using NVL(trt_upd_count,0) + 1 instead of trt_upd_count + 1.
Finally, watch out for usages of :new and :old. It looks like they are correct in this trigger, but it will depend on your business case.
In the IF INSERTING section of your trigger you have
UPDATE B
SET trt_ins_count = trt_ins_count+1
WHERE :old.trt_procedure = :new.trt_procedure;
When inserting a new row all values in the :OLD pseudorow are NULL and thus your UPDATE will never update anything. I think you meant
UPDATE B
SET trt_ins_count = trt_ins_count+1
WHERE B.trt_procedure = :new.trt_procedure;
Give that a try and see if that helps solve your problem.

Oracle cannot use IMGSilimar for ORDImage

I have the following procedure.
CREATE OR REPLACE PROCEDURE FIND_SIMILAR_PICTURES
( nazwa in varchar, exp in varchar)
IS
idk number(10);
img_score number;
image ORDSYS.ORDImage;
query_sig ORDSYS.ORDImageSignature;
text varchar(200) := 'shape="1.0"';
CURSOR photos IS SELECT idk, IMGScore(1), obrazek FROM foto_oferty WHERE ORDSYS.IMGSimilar(image_sig,query_sig,text,10,1) = 1;
BEGIN
SELECT image_sig INTO query_sig FROM foto_oferty WHERE nazwa_pliku = nazwa;
OPEN photos;
LOOP
FETCH photos INTO idk, img_score, image;
EXIT WHEN photos%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Obrazek z id '||idk||'pasuje.');
END LOOP;
CLOSE photos;
END;
Structure of table.
CREATE TABLE foto_oferty(
idk number(10) NOT NULL,
nazwa_pliku varchar(40) NOT NULL,
obrazek ORDimage,
modyf ORDimage,
oferta_id number(10) NOT NULL,
image_sig ORDImageSignature,
CONSTRAINT foto_oferty_pk PRIMARY KEY(idk)
);
When I run this procedure I get that error.
Error(9,76): PL/SQL: ORA-00904: "ORDSYS"."IMGSIMILAR": invalid identifier
Is it the problem that I don't use properly method IMGSimilar?
I should think the following query would tell you if your object exists and is visible to you
SELECT
*
FROM all_procedures
WHERE owner = 'ORDSYS'
AND
(
(procedure_name LIKE '%IMG%')
OR
(procedure_name LIKE '%SIM%')
)
ORDER BY all_procedures.procedure_name
;
If the object is available you can find entry points in the schema browser of whichever SQL tool you are using.

Oracle - How to Create Table with Two Columns that grow like 2D array?

I want to create a table for logging purpose in such a way that when I will insert into table I have an Execution order column that increment per RequestID-wise.
CREATE TABLE WSRequestLog
(
RequestId NUMBER,
ExecOrder INTEGER,
MobileNo VARCHAR2(50),
CardNo VARCHAR2(50),
Log_Text VARCHAR2(4000),
DateTime date
PRIMARY KEY (RequestId, ExecOrder)
);
PROCEDURE Generate
.
.
.
IF first_condition = TRUE THEN
INSERT INTO WSRequestLog (RequestId, ExecOrder, MobileNo, CardNo, Log_Text, DateTime)
VALUES (v_req_id, Auto_Incremenet or NextVal, v_mobile_no, v_card_no, 'Performing First Step', SYSDATE);
--Execute Code
IF second_condition = TRUE THEN
INSERT INTO WSRequestLog (RequestId, ExecOrder, MobileNo, CardNo, Log_Text,DateTime)
VALUES (v_req_id, Auto_Incremenet or NextVal, v_mobile_no, v_card_no, 'First Step executed, checking next step', SYSDATE);
--Execute Code
ELSE
INSERT INTO WSRequestLog (RequestId, ExecOrder, MobileNo, CardNo, Log_Text,DateTime)
VALUES (v_req_id, Auto_Incremenet or NextVal, v_mobile_no, v_card_no, 'Second Step not applicable', SYSDATE);
--Execute Code
END IF;
END IF;
END Generate;
My question is how to achieve this type of insertion?
So that if I execute the Stored Procedure, the log table would be like this:
Have a package which is pragma serially reusable which will have one variable set to null.
In other package which contains core logger code, verify if the variable is null then set request id variable value - which is a package variable- You will increment this value in your case. for exec order follow the logic as in below lines
procedure set_log_sequence(p_log_sequence in number) as
begin
if p_log_sequence is null then
gv_log_sequence := gv_log_seq;
gv_log_seq := gv_log_seq+1;
else
gv_log_sequence := p_log_sequence;
end if;
end;

Cast SYS_REFCURSOR to a PL/SQL Type

I have a stored procedure that calls a function that returns a SYS_REFCURSOR. The function returns a SYS_REFCURSOR because this function is also called from Java application and Java does not understand rowtype.
Here is my function.
function f_get_building(
p_building_id in T_BUILDING.ID%type
) return sys_refcursor
AS
v_cursor sys_refcursor;
BEGIN
open v_cursor for
select
BUILDING_ID,
CAMPUS_ID,
DELETE_FLAG,
max(EFFECTIVE_DATE),
END_DATE,
IMAGE_URL,
INSTITUTION_ID,
LOCAL_ID,
LOCATION_ID,
NAME
from V_BUILDING
where BUILDING_ID = p_building_id
group by
BUILDING_ID,
CAMPUS_ID,
DELETE_FLAG,
END_DATE,
IMAGE_URL,
INSTITUTION_ID,
LOCAL_ID,
LOCATION_ID,
NAME;
return v_cursor;
END f_get_building;
In another stored procedure I am also calling this function but having issues using it. Here is the stored procedure.
procedure sp_delete_building(
p_building_id in T_BUILDING.ID%type,
p_permanent_delete in boolean default false
)
AS
v_building_cur sys_refcursor;
v_building_rec V_BUILDING%rowtype;
BEGIN
-- if permanment delete
if p_permanent_delete = true
then
delete from T_BUILDING where ID = p_building_id;
-- otherwise perform soft delete
else
-- lookup
v_building_cur := f_get_building(p_building_id);
-- if cursor is empty there is nothing to do
if v_building_cur%notfound then
return;
end if;
fetch v_building_cur into v_building_rec; -- this line is where the error happens
-- if its already deleted nothing to do
if v_building_rec.DELETE_FLAG = 'Y'
then
return;
else
insert into T_BUILDING_ATTRIBUTE(BUILDING_ID,EFFECTIVE_DATE,DELETE_FLAG,
IMAGE_URL,LOCATION_ID,NAME)
values (v_building_rec.BUILDING_ID,current_timestamp,'Y',v_building_rec.IMAGE_URL
,v_building_rec.LOCATION_ID,v_building_rec."NAME");
end if;
end if;
END sp_delete_building;
I am getting the following PL/SQL stacktrace.
ORA-01722: invalid number
ORA-06512: at "OBR.PKG_BUILDING", line 114
ORA-06512: at line 8
Forgive my ignorance, this is my first project using PL/SQL, I would classify myself as a Java developer, not a database developer. Since I am selecting everything from V_BUILDING I expected I would just be able to case it as a rowtype inside the stored procedure. How can I use my function inside my stored procedure?
Update:
Here is the create statement for V_BUILDING
CREATE OR REPLACE FORCE VIEW "OBR"."V_BUILDING" ("BUILDING_ID", "LOCAL_ID", "INSTITUTION_ID", "EFFECTIVE_DATE", "END_DATE", "DELETE_FLAG", "CAMPUS_ID", "LOCATION_ID", "IMAGE_URL", "NAME") AS
SELECT
ba.BUILDING_ID,
b.LOCAL_ID,
b.INSTITUTION_ID,
ba.EFFECTIVE_DATE,
NVL(MIN(ba2.EFFECTIVE_DATE - INTERVAL '0.000001' SECOND),TO_DATE('31-DEC-9999', 'DD-MON-YYYY')) AS END_DATE,
ba.DELETE_FLAG,
ba.CAMPUS_ID,
ba.LOCATION_ID,
ba.IMAGE_URL,
ba.NAME
FROM
T_BUILDING b
INNER JOIN T_BUILDING_ATTRIBUTE ba
ON b.ID = ba.BUILDING_ID
LEFT JOIN T_BUILDING_ATTRIBUTE ba2
ON ba.BUILDING_ID = ba2.BUILDING_ID
AND ba2.EFFECTIVE_DATE > ba.EFFECTIVE_DATE
GROUP BY
ba.BUILDING_ID,
b.LOCAL_ID,
b.INSTITUTION_ID,
ba.EFFECTIVE_DATE,
ba.DELETE_FLAG,
ba.CAMPUS_ID,
ba.LOCATION_ID,
ba.IMAGE_URL,
ba.NAME
ORDER BY ba.BUILDING_ID, ba.EFFECTIVE_DATE DESC;
Update 2:
Here is a screenshot of the types in the view
CAMPUS_ID - NUMBER(10)
LOCATION_ID - NUMBER(10)
IMAGE_URL - VARCHAR(500)
NAME - VARCHAR(255)
BUILDING_ID - NUMBER(10)
LOCAL_ID - VARCHAR(30)
INSTITUTION_ID - NUMBER(10)
EFFECTIVE_DATE - TIMESTAMP(6)
END_DATE - TIMESTAMP (6)
DELETE_FLAG - CHAR(1)
Here are the list of columns and their datatypes as returned by the view and the ref cursor:
LIST OF COLS FROM VIEW DATATYPE FROM VIEW LIST OF COLS FROM CURSOR DATATYPE FROM CURSOR
---------------------- ------------------ ------------------------ --------------------
BUILDING_ID NUMBER(10) BUILDING_ID NUMBER(10)
LOCAL_ID VARCHAR(30) CAMPUS_ID NUMBER(10)
INSTITUTION_ID NUMBER(10) DELETE_FLAG CHAR(1)
EFFECTIVE_DATE TIMESTAMP(6) max(EFFECTIVE_DATE) TIMESTAMP(6)
END_DATE TIMESTAMP(6) END_DATE TIMESTAMP(6)
DELETE_FLAG CHAR(1) IMAGE_URL VARCHAR(500)
CAMPUS_ID NUMBER(10) INSTITUTION_ID NUMBER(10)
LOCATION_ID NUMBER(10) LOCAL_ID VARCHAR(30)
IMAGE_URL VARCHAR(500) LOCATION_ID NUMBER(10)
NAME VARCHAR(255) NAME VARCHAR(255)
They are not the same, yet by using the V_BUILDING%ROWTYPE in your sp_delete_building procedure, you're treating the ref cursor results as if the column order is the same as that of the view.
You can see that there are several mismatches between the datatypes of the view and the cursor select lists - it's probably the "LOCATION_ID/LOCAL_ID" mismatch that's causing the invalid number error that you're seeing.
You either need to change the order of your ref cursor so that the list of columns is returned in the same order as that of the view, or to explicitly list the columns of the cursor in the v_building_rec record type.
As an aside, you should give your max(EFFECTIVE_DATE) column in the refcursor an alias.

Resources