I have this trigger in one of my scripts:
CREATE OR REPLACE TRIGGER MS_DB.DB_TR_IncrementTrialNumber BEFORE INSERT
ON MS_DB.DB_SUMMARY FOR EACH ROW
begin
UPDATE MS_DB.DB_Summary SET MS_DB.DB_Summary.TimesGenerated =
(Select COALESCE(MAX(TimesGenerated),0)+1
From MS_DB.DB_Summary
Where MS_DB.DB_Summary.StepID = :NEW.StepID And
MS_DB.DB_Summary.ValidationID = :NEW.ValidationID AND
MS_DB.DB_Summary.SummaryDate = :NEW.SummaryDate);
where MS_DB.DB_Summary.ID = :NEW.ID;
end;
/
I use TOAD for executing the the script.
When I use 'Execute as Script' button it works fine.
But when I run it in SQLPlus window I get this line :
SP2-0552: Bind variable "NEW" not declared
Any ideas why I am getting this?
Thanks
By default SQL*Plus treats a blank line as the end of a statement. The first line, the create, is never executed. The rest is executed as an anonymous block, and as it is no longer part of a trigger statement the NEW isn't recognised.
You can either remove the blank line before the begin, or do set sqlblanklines on before you start.
Related
How to prompt a message if field is empty in oracle forms i'm not sure if it works and the trigger i'm using is when-validate-item
begin
if date = NULL then
message('please enter issue date')
else
null;
end if;
end;
From my point of view:
you should edit field's properties and set the required property to yes and let Forms worry about it
if you insist on reinventing the wheel, then don't just display a message as it is pretty much useless - user can ignore it. Raise an error, instead
if :block_name.item_name is null then
message('Please, enter issue date');
raise_form_trigger_failure;
end if;
Put that piece of code into the WHEN-VALIDATE-ITEM trigger.
Just modify the code a little bit as
converting date = NULL to :date IS NULL, since : prepended to
the field's name within the code
add an extra message(''); (exactly this with blank padded
argument) if a pop-up message box needed
don't forget the semicolon at the end of the line of the current
message(....)
as invoking from one of the WHEN-VALIDATE-ITEM or WHEN-NEW-ITEM-INSTANCE triggers
I know ORA-01722 occurs when I try to convert an invalid character to number. For example: "a123". In this case I only try to make a where condition, where the parameter is the ID of the table and the parameter is defined based on table type.
PROCEDURE SP_CPR_AGRUPAR_COMPRA(ID_SOLICITUD IN cpr_solicitud.id%type, ID_GRUPO IN cpr_solicitud.ID_GRUPO%type ) AS
BEGIN
UPDATE cpr_solicitud
SET ID_GRUPO=ID_GRUPO
WHERE id=ID_SOLICITUD;
END SP_CPR_AGRUPAR_COMPRA;
I try to format the ID_SOLICITUD with TO_NUMBER function but the error continue. Something like this:
UPDATE cpr_solicitud
SET ID_GRUPO=ID_GRUPO
WHERE id=TO_NUMBER(ID_SOLICITUD);
I did a test passing directly the information and it works.
UPDATE cpr_solicitud SET ID_GRUPO = 18 WHERE id = 942000;
I did many test and the conclusion is that the error is related to the ID_SOLICITUD parameter. I don't why but if I pass the ID_GRUPO and I leave the ID_SOLICITUD it works.
It's works:
UPDATE cpr_solicitud
SET ID_GRUPO=ID_GRUPO
WHERE id=1
It's not works:
UPDATE cpr_solicitud
SET ID_GRUPO=1
WHERE id=TO_NUMBER(ID_SOLICITUD);
As stated in the documentation:
If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence.
Caution: When a variable or parameter name is interpreted as a column name, data can be deleted, changed, or inserted unintentionally.
In your code,
SET ID_GRUPO=ID_GRUPO
clearly falls into that warning, as #Bob hinted. Every row that matched the filter would be updated with it's current value (i.e. nothing changes), not the value passed into the procedure. As you've confirmed in a comment that the table has a column called ID_SOLICITUD too, so does:
WHERE id=ID_SOLICITUD;
You are getting the error because it is implicitly converting the column value from ID_SOLICITUD - which is presumably not numeric - to a number so it can be compared with id. The ID_SOLICITUD parameter value is not being used, so its data type isn't relevant. You are effectively doing:
UPDATE cpr_solicitud
SET cpr_solicitud.ID_GRUPO=cpr_solicitud.ID_GRUPO
WHERE cpr_solicitud.id=cpr_solicitud.ID_SOLICITUD;
which clearly isn't what you intended. If you run that statement on its on you'll get the same error.
You can either prefix the variable names with the object they actually belong to:
PROCEDURE SP_CPR_AGRUPAR_COMPRA(ID_SOLICITUD IN cpr_solicitud.id%type, ID_GRUPO IN cpr_solicitud.ID_GRUPO%type ) AS
BEGIN
UPDATE cpr_solicitud
SET ID_GRUPO=SP_CPR_AGRUPAR_COMPRA.ID_GRUPO
WHERE id=SP_CPR_AGRUPAR_COMPRA.ID_SOLICITUD;
END SP_CPR_AGRUPAR_COMPRA;
or (more simply and safely, perhaps) change the names, e.g. with a simple prefix:
PROCEDURE SP_CPR_AGRUPAR_COMPRA(p_ID_SOLICITUD IN cpr_solicitud.id%type, p_ID_GRUPO IN cpr_solicitud.ID_GRUPO%type ) AS
BEGIN
UPDATE cpr_solicitud
SET ID_GRUPO=p_ID_GRUPO
WHERE id=p_ID_SOLICITUD;
END SP_CPR_AGRUPAR_COMPRA;
This is a strange one. I have a simple toggle update statement that when ran in TOAD works just fine (the test record's ID is 10000244999201)...
update myTable set
hasbeenread = case when (hasbeenread = 0) then 1 else 0 end
where id = 10000244999201;
This update statement is also in a package/procedure that can be called from ColdFusion and when it's called this way it does not work. The procedure runs and I get success back but the update doesn't toggle the hasbeenread column.
procedure toggleRead(p_webSession number, p_data lib.jsonclob, result out lib.jsonclob) is
ws websession%rowtype := lib.getWebSession(p_webSession);
pin lib.paramArray := lib.jsonToArray(p_data);
begin
--(1) Do perm checks here
--(2) Do data validation here
--(3) Code your process here
--(4) Send back a proper JSON/XML response.
delete from debuglog where title = 'gtest';
insert into debuglog ( username, seqno, title, cfd01, insertdate )
values ( 'GADMIN', 555, 'gtest', pin('id'), sysdate );
commit;
update myTable set
hasbeenread = case when (hasbeenread = 0) then 1 else 0 end
where id = pin('id');
result := lib.response(true,null,null);
exception
when others then
err.logAndEmailError( ws.fullName, gbody_version, 'toggleRead - p_data: '||p_data||', SQLERRM: '||sqlerrm );
end toggleRead;
I have verified the pin('id') value by looking at the debug log that happens right before the update, it is the correct id. I have even replaced pin('id') and hardcoded 10000244999201 into the where clause, that still didn't work. I tried putting a commit; after the update (which I shouldn't have to do because ColdFusion will commit when it comes back since I'm not using a cftransaction tag around it), that still didn't work. But when I remove the CASE statement and hardocde it to hasbeenread = 0 or hasbeenread = 1 it then works. So the problems looks like it has to do with the CASE statement. But like I said, it works fine when I run that update in TOAD. What am I missing?
Thanks!
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
ColdFusion version: 11,0,0,289974
UPDATE: Here is the ColdFusion call...
<cfstoredproc procedure="lib.getJson" datasource="#session.sv.ds#" returncode="no">
<cfprocparam type="in" cfsqltype="cf_sql_decimal" variable="webSession_in" value="#session.sv.csid#">
<cfprocparam type="in" cfsqltype="cf_sql_clob" variable="data" value="#z.data#">
<!---
How to get back a clob
Here they say to use CF_SQL_LONGVARCHAR
http://stackoverflow.com/questions/11053539/getting-clob-data-from-coldfusion-8
<cfprocparam type="out" cfsqltype="cf_sql_longvarchar" variable="result">
But instead we use CF_SQL_CLOB but then do the ArrayToList part you see below.
--->
<cfprocparam type="out" cfsqltype="cf_sql_clob" variable="z.result">
</cfstoredproc>
<cfif notnull(z.result)>
<cfset z.result = ArrayToList(z.result,"")>
</cfif>
<cfreturn z.result />
UPDATE: When I call the proc from TOAD it works, the update works and the column value toggles...
declare
r clob;
begin
c3.toggleread(146992,'{"ID":10000244999201}',r);
dbms_output.put_line(r);
end;
/
One common way it can fire twice is the use of a custom tag. For example if you put your stored proc in a custom tag and called it like this:
<Cf_toggleuser z="#mydata#"/>
Custom tags have 2 "execution modes" - start and end. They are referenced as attributes of the "thistag" scope within the contents of the tag. The tag (by design) runs two times - a start and and end. This is so you can run them with content inbetween - commonly done for altering layout or display content as in:
<cf_layout>
...some content here
</cf_layout>
But it also means if you intend to ONLY run the contents of the tag one time you need to include a check and only run it for one of the modes as in:
<cfif thistag.executionmode IS 'Start'>
...run the procedure
</cfif>
This may not be your problem but it is one nuance that occurs that is easy to miss. In your case the results were an error in data.
NOTE: you can also pull out the final slash in your tag (or the end tag) to cause it to execute only once. To illustrate:
This call only executes one time:
<Cf_toggleuser z="#mydata#">
While this call executes twice:
<Cf_toggleuser z="#mydata#"/>
I have associated the following function to a tests in order to select a row in a java table when a the row text matches an expected value :
Public Function GetRowWithCellText(ByRef oJTable, sColName, sText)
bChkText=FALSE
iRowCount=oJTable.GetROProperty("rows")
For iCounter=0 to iRowCount-1
sGetCellText=oJTable.GetCellData(iCounter, sColName)
If instr(sText, sGetCellText)>0 Then
bChkText=TRUE
GetRowWithCellText=iCounter
End If
Next
ReportingFunction bChkText, "Row with desired text"
End Function
RegisterUserFunc "JavaTable", "GetRowWithCellText", "GetRowWithCellText", TRUE
The function is well registered and I got it in the list of available functions for a java table.
However when trying to apply the function into a JavaTable in my application :
JTable.GetRowWithCellText msg.users.list.table.header.user , LOGIN
I get the following error :
Object required: 'msg'
Line (122): "JTable.GetRowWithCellText msg.users.list.table.header.user , LOGIN".
Please note that UFT is not recoginising cols of my table so I had inserted its value manually
It appears from the 'Object required' error that the value for 'msg' is not defined. The first part of msg.users.list.table.header.user refers to an object named 'msg'. If that object does not exist or has not be initialized, you may get that error.
You can break your statement up to confirm where the error is located. Change this statement
JTable.GetRowWithCellText msg.users.list.table.header.user , LOGIN
To these statements
Dim user
Set user = msg.users.list.table.header.user
JTable.GetRowWithCellText user, LOGIN
When you re-execute, you should get an error on the second line if there was an issue with msg; otherwise you will get an error on the third line if it is truly an issue with your function.
I have used column index instead of column name and it worked , I guess there is an issue with special characters.
Thanks
I have a cursor which is returning certain value. I would like to assign this value to a text field. When I compile trigger it returns error: "bad bind variable" for new_dr.textitem43. Any help greatly appreciated.
declare
EMP_ID_VALUE number :='NEW_EMP.ID_FIELD';
pcv_no pcv%TYPE;
cursor cursor_dr IS
select pcv FROM drivers
where drivers.eno = EMP_ID_VALUE;
begin
IF EMP_ID_VALUE < 1000 THEN
open cursor_dr;
fetch cursor_dr into pcv_no;
:new_dr.textitem43 := 'pcv_no';
exit when cursor_dr%NOTFOUND;
CLOSE cursor_dr;
ELSIF
...
END IF;
end;
That would indicate to me that either there is no block named new_dr or there is no field named textitem43 in that block. Are you sure you don't really mean :new_emp.textitem43?