Im trying to debug Netezza procedure using RAISE NOTICE after UPDATE AND INSERT queries. Im trying to show the current time after each query is finished.
I tried something like this:
RAISE NOTICE 'UPDATE time=%', now();
But that doesn't work. Only way I have had it working is to define a timestamp variable at the beginning of procedure and then just before raising notice I define this variablie like this:
timevar:=now();
RAISE NOTICE 'UPDATE time=%', timevar;
Is there a way where I can combine it just in one line and not have to define a new variable at beginning of procedure and assining it now() each time I whant to RAISE NOTICE ?
When you want to track progress through several steps in the same transaction, you can't use now() as that won't change.
It's a feature of transaction management within Postgres, that all statements within the same transaction get the same value for now()
However timeofday() DOES change, so you can use that.
And you can use a function in the place of identifier:
RAISE NOTICE 'UPDATE time=%', timeofday();
RAISE only accepts identifiers as arguments after the format expression. The way you are currently doing it is really the only way.
The statement syntax follows:
RAISE level ’format’ [, identifier [...]];
Related
I am not too familiar with Oracle but I have written a trigger for my application to generate numbering for records using a sequence. The problem I have is, the numbers may already be in use and I want to add a check to ensure if the number is already used, to select the next one available from the sequence. Can this be done firstly and if so, any assistance would be really appreciated?
DROP TRIGGER COMPLAIN_TRG_ENQUIRYNO;
CREATE OR REPLACE TRIGGER COMPLAIN_TRG_ENQUIRYNO
BEFORE INSERT
ON COMPLAIN REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
l_enquiry_no_end complain.enquiry_no_end%TYPE;
BEGIN
SELECT seq_enquiryno.NEXTVAL INTO l_enquiry_no_end FROM dual;
IF :NEW.ENQUIRY_NO_END = ' ' THEN
:NEW.ENQUIRY_NO_END := l_enquiry_no_end;
END IF;
EXCEPTION
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END ;
Don't use a sequence if you have existing (numeric) data in the column as this can lead to duplicates. Either start from empty and use a sequence or if you are really stuck find the maximum pk you have and reset the startswith property of the sequence.
Alternatively you could use guids instead of guids which have the advantage of always being globally unique - call the sys_guid() function in your trigger. They can lead to other issues with indexing etc though.
We know that it is possible to dynamically figure out the name of the procedure or package that is currently executing as explained here and here. This generally applies to statements being executed from other stored procedures (compiled) in the database.
The problem:
We have been trying to log all UPDATE activity on a specific column (called STATE) by placing a trigger on the table and invoking who_called_me from within the trigger. The purpose of doing this is apparently as per the application design the column STATE could get updated by multiple pieces of code (residing in the database) based on certain business conditions. In addition to that, the column could also get updated by the application which is a hibernate based application and at times when the update happens by a hibernate query the who_called_me function returns nothing. There are multiple parts in the application that could also UPDATE the column STATE based on certain conditions.
The who_called_me strategy is working well for us in cases where a stored procedure (which resides in the database) issues the UPDATE statement and who_called_me is successfully capturing the corresponding owner, name, line no. etc. of the stored procedure. But in case the UPDATE happens from hibernate, the function captures no details.
Is there a way to capture which hibernate query UPDATEd the row through the trigger? Or is there any other way?
Note: The trigger code is similar to the answer posted on this question.
you can track the query with ora_sql_text function, e.g. this is the function I use for that:
-- getting sql code, which is calling the current event, as clob
function getEventSQLtext
return clob
is
sqllob clob;
sql_text ora_name_list_t;
dummy integer;
begin
dummy := ora_sql_txt(sql_text);
dbms_lob.createtemporary(sqllob,false);
for i in 1..sql_text.count loop
dbms_lob.writeappend(sqllob,length(sql_text(i)),sql_text(i));
end loop;
return sqllob;
if dummy is null then null; end if; -- removing warning of non-used variable :)
end;
This will be a query which is generated by hibernate and this is the only information you can get because this should be the only thing hibernate can do with DB.
It turns out, the who_called_me approach works better for stored procedure calls where the stack trace can point exactly which line invoked a DML. In, case of hibernate it is possible that the code may not call a stored procedure but in-turn may have individual DMLs which get invoked based on certain conditions. As opposed to other answer given by #simon, the ora_sql_txt function may only work in system event triggers or I may be wrong, but either way it is not capable of capturing the SQL Statement issued by Hibernate (tested that it does not works and retunrs a NULL value).
So at the end of the day, to find what SQL Hibernate is using, DB Trace files and Hibernate debug level logs is the only way for now.
I am in the process of migrating from MySQL to PosgreSql and an have a slight problem with a proc/function I want to call in a batch update.
How can I perform an update on a Postgresql function when it always seems to return a value even if you declare the value to be void.
This is just a simple example to illustrate the problem.
CREATE OR REPLACE FUNCTION update_function(
IN i_id bigint)
RETURNS void AS $$
DECLARE
d_id bigint;
BEGIN
UPDATE test_table set id = '' where id = i_id;
RETURN;
END;
$$ LANGUAGE plpgsql;
If I call this using a SpringTemplate.update() method it has the error "org.postgresql.util.PSQLException: A result was returned when none was expected."
If you call update and it returns a value it throws an error I understand that, so.
My question is, is there any way for a postgresql function to not return a value or will I need to find an alternative way to do the batch update? I should mention that the reason I want to do the update using a function is there is a number of tables being updated in the proc/function the above is just a simple explanation.
An alternative could for me to parse in an array of input values and loop over them.
As I understand it your problem is that PostgreSQL will add a row to the result set even though your function didn't return one. A quick test showed that, in fact, these are returning a null from PostgreSQL.
What I do (and I realize this may not be the Spring way) is to have a function that does what I need it to do, and returns a useful value. Then I take that value and use it for sanity checking purposes. I might, for example, return the total number of rows updated (or perhaps the most recent version of the parent-most row) and hand that back to the application to use.
However, yes, you will need to find another way to do this.
I am testing this perl script which basically call procedure and run DELETE on 2 tables.
Questions:
Is there any issue with the procedure or calling procedure in perl?
Can I use 2 deletes in single procedure?
Procedure delete (v_db_id in number)
IS BEGIN
DELETE from TAB1
where db_id = v_db_id;
DELETE from TAB2
where db_id = v_db_id;
END delete;
PERL Script:
sub getdelete {
my $dbID = shift
my $rs;
my $SQL;
$SQL = q{delete (?)};
$rs = executeQuery($SQL,$dbID);
$rs -> fetchrow();
$rs -> finish();
}
PERL Script calling subroutine getdelete as below:
&getdelete ($dbID);
Error:
DBD::Oracle::st execute failed: ORA-00900: invalid SQL statement (DBD Error: OCIStmtExecute)[for statement "delete"]
DELETE doesn't takes an expression that results in a table id; it takes a table id literal. As such, you can't use replaceable parameters. You need to construct the table id literal, which $dbh->quote_identifier can do.
my $sql = 'DELETE '.$dbh->quote_identifier($dbID);
$dbh->do($sql);
You are using a module that wraps DBI in a very poor way1. I have no way of knowing if it'll give access to the database handle or to the handle's quote_identifier method, but at least now you know what to look for.
Notes:
There are three ways to wrap DBI that make sense:
To add functions or override some minor aspect of existing functions.
For example, DBI database statements don't have the selectrow_* methods founds on database handles. Adding these without restricting access to the rest of DBI is perfectly fine.
To provide a higher level abstraction of a database, such as an ORM like DBIx::Class. These are massive systems with thousands if not tens of thousands of lines.
If your wrapper provide a new database interface and its code fits on two screens, it's doing something wrong.
To centralise all DB code by providing application-specific functions like create_user, fetch_daily_report_data, etc. SQL isn't passed
If your wrapper attempts to this but provides functions that expect SQL, it's doing something wrong.
What doesn't make sense is to attempt to simplify DBI, and this appears to be what your wrapper does. DBI actually provides a very simple interface. Any attempts to simplify it is bound to leave out something critical.
<-------PeopleCode------>
Hi,
I have a SQL query that i have tried executing using both SQLEXEC and SQL.fetch() but the problem is, when I am passing the values to parameters (:1,:2...) it does not return a row but when I hardcode the values in the where clause of the query itself, it retrieves the correct value.
Can anybody help?
My query looks similar to the following sample query :
Select * from PS_rec1 where emplid=:1 and plan_type=:2
it returns no data till i hardcode the values.
I have checked the values at the back end and some data is there to be fetched. Moreover, the same query retrieves data when ran in TOAD.
Have you tried outputting your binds to a log file just before you use them in your SQL statement?
If the binds aren't working, but literals are, then perhaps your binds don't contain the values that you expect them to.
You could also try explicitly setting the binds to the values that you're expecting just before the SQL statement. This will prove that the way you're passing in the binds is working correctly.
It required another update to the same record to get the values fetched in SQL exec.
M not sure what was the problem but i guess it might be that the previous update did not write the changes to the db even after an explicit commit.
Ok, you need to put your exact SQLExec statement in the question.
But, do you really have "Select * ..." in a SQLExec? How many columns are in your table? Since you mention the where clause, is your statement
SQLExec("select * from PS_rec where emplid=:1 and plan_type=:2", &var1, &var2, &vartocontainthewholerow);
Which will work in a SQL tool (toad) but probably does not work in AE or any type of Peoplecode program.
Now if your table has three columns, should you not have something like this:
SQLExec("select emplid, plan_type, column3 from PS_rec where emplid = :1 and plan_type=:2", &emplidIn, &plan_typeIn, &emplidOut, &plan_typeOut, &column3Out);
Notice that with three columns in the table that emplid and plan_type are two of them, you need to list all the columns you want, not asterisks '*'. Kind of silly to select the emplid and plan_type though.