stored procedure in informix - informix

I tried to create a sample stored procedure in informix but it gives me a syntax error. Can any one say whats wrong with this?
drop procedure if exists sample();
create dba procedure sample()
update employee set last_name="Tietz" where emp_id = '2537';
end procedure;
Thanks

The IF EXISTS clause is only available in very recent versions of Informix. I've got a couple of instances handy: 11.50.FC2 and 11.70.FC7. The statement DROP PROCEDURE IF EXISTS foobar() works on the later one only.
The rest of it looks OK to me.

Related

How to call the stored procedure in Snowflake

I want to call the procedure created in main account from a reader account
I have couple of tables shared between them:
Employee
Procedure
Procedure table contains procedure names (to be called in main account) and id.
Calling the procedure as below but unable to do so
set var1 = (select procedure_name from procedure_calls);
call $var1;
Please let me know is it possible to call the way I am calling ?
I want to call the procedure created in main account from a reader
account
Currently, you can't do this from a reader account. A reader account can run select queries on the tables and secure views its parent account shares to it, and that's all it can do. It can't run other statement types including CALL.
You need to wrap the string with the stored procedure name in a literal identifier():
set sp = 'Load_Employee';
call identifier($sp)()
https://docs.snowflake.com/en/sql-reference/identifier-literal.html
Example - I have a stored procedure
copy_into_temp_table(table_name VARCHAR)
It can be called via the below statement
CALL copy_into_temp_table(EMP_TBL);

PL SQL - Procedure - table that holds a record of users who executed a procedure

Hi and apologies in advance if the question has already been asked. I haven't been able to come across the answer.
I'm wondering if there is a table that holds a record of oracle usernames that have executed a particular procedure or function.
I'm trying to create a procedure that can be called as a subprogram by another procedure. The procedure which i'm looking to create will create a log entry every time the other procedure is executed. Example below;
User_Name = The Oracle user name of the person who executes the function.
Name = The name of the procedure or function.
LastCompileDT = The date/time the function or procedure was last compiled.
I'm a bit stuck on where to source the data from.
I've come across the all_source table but it only gives me the owner of the procedure and not the executing user.
Any feedback would be greatly appreciated.
Thanks
There might be a couple of ways to do that. Maybe someone else can suggest a method of extracting all this data from one data dictionary view. However, my method would be like this:
User_Name: use the keyword USER. It returns the Oracle user that executed the procedure:
SELECT USER FROM DUAL;
However, if you are interested in the OS user who executed that procedure, then you can use the following
SELECT sys_context( 'userenv', 'os_user' ) FROM DUAL;
More on this here. To my knowledge, this can be fetched on the fly only, and it is not logged anywhere by default. So you need to run it when you call the procedure.
Procedure Name: &
LastCompileDT : can be fetched from the view USER_OBJECTS
SELECT OBJECT_NAME, LAST_DDL_TIME
FROM USER_OBJECTS
WHERE OBJECT_TYPE = 'PROCEDURE'
AND OBJECT_NAME = '<YOUR PROCEDURE NAME>';
Rather than rolling your own audit, you could use the inbuilt auditing table provided.
See https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_4007.htm
--Create a test procedure as an example
CREATE PROCEDURE my_test_proc
AS
BEGIN
NULL;
END my_test_proc;
--Turning on auditing executions of the proc
AUDIT EXECUTE ON my_test_proc BY ACCESS WHENEVER SUCCESSFUL;
--Run the proc
EXEC my_test_proc;
--check audit history
SELECT *
FROM dba_common_audit_trail cat
WHERE cat.object_name = 'MY_TEST_PROC';
The dba_common_audit_trail table has columns DB_USER, and OBJECT_NAME for your User_Name/Name.
For the last compiled time see Hawk's answer, or if you want to see a history of last DDL times you can add this to the audit
--Turn on auditing of creating procs
AUDIT CREATE PROCEDURE BY ACCESS;

Replace stored procedure with MyBatis mapping

I can not find an example of mapping in MyBatis that I can replace the below code with.
"if sqlcode <> 0" If no update takes place then do an insert
Any sugestions? :)
as
begin
execute SetDefaultIsolationLevel
update COMPANYLEVEL
set
companylevelid = #companylevelid,
companynameid = #companynameid,
level = #level,
memo = #memo,
operator = #operator,
changed = getdate(*)
where
companynameid = #companynameid
if sqlcode <> 0
BEGIN
insert into COMPANYLEVEL
(companylevelid,companynameid,level,memo,operator,changed)
values
(#companylevelid,#companynameid,#level,#memo,#operator,getdate(*))
END
commit transaction
end
I don't think MyBatis has any mapping to say "try an update, if that fails do an insert". If you want that done in one round trip to the database, then a stored procedure is appropriate. You can call this stored procedure from MyBatis, but the if/else logic would be in the stored proc.
If you are trying to get rid of the stored proc, then you'll need a two step check in your code. An update in MyBatis returns the number of rows updated (via the JDBC driver), so if that is zero, then you can call a MyBatis insert mapping. In cases where an insert occurs, it would require two round trips to the database.
You could also do an "upsert" using a MERGE statement in a stored proc, but that of course isn't related to MyBatis other than MyBatis can call your stored proc. It looks like you are using Sybase? If so, I'm not sure if Sybase has upserts - link to research: Upsert (update or insert) in Sybase ASE?

Hot to get stored procedure SQL text?

Is there any way to retrieve (and update) the actual stored procedure SQL text from a data dictionary?
A sample use case for this would be to write a replacement tool for the Advantage Data Architect. However at the moment I really need this to workaround a bug in ADS 9.1.
I imagine there must be something like:
EXECUTE PROCEDURE sp_GetStoredProcedureProperty('PROCNAME', 'SQLTEXT');
I found a system procedure called sp_ModifyProcedureProperty that can be used to modify some parts of a SP:
http://devzone.advantagedatabase.com/dz/WebHelp/Advantage10.1/index.html?master_sp_modifyprocedureproperty.htm
There is a system table in the dictionary called system.storedprocedures which has a field named SQL_Script that does what I need.
Example:
SELECT SQL_Script FROM system.storedprocedures WHERE Name = 'PROCNAME';

Delphi ClientDataset Read-only

I am currently testing with:
A SQLConnection which is pointed towards an IB database.
A SQLDataset that has a SQLConnection field set to the one above.
A DatasetProvider that has the SQLDataset in (2) as its Dataset field value.
A ClientDataset, with the ProviderName field pointing to the provider in (3).
I use the following method (borrowed from Alister Christie) to get the data...
function TForm1.GetCurrEmployee(const IEmployeeID: integer): OleVariant;
const
SQLSELEMP = 'SELECT E.* FROM EMPLOYEE E WHERE E.EMPLOYEEID = %s';
begin
MainDM.SQLDataset1.CommandText := Format(SQLSELEMP, [Edit1.Text]);
Result := MainDM.DataSetProvider1.Data;
end;
Which populates the DBGrid with just one record. However, when I manually edit the record, click on Post, then try to commit the changes, using
MainDM.ClientDataset1.ApplyUpdates(0); // <<<<<<
It bombs, with the message "SQLDataset1: Cannot modify a read-only dataset."
I have checked the ReadOnly property of the Provider, and of the ClientDataset, and the SQL has no joins.
What could be causing the error?
It appears that your ClientDataSet.Data property is being populated from the Data property of the DataSetProvider. With the setup you described, you should be able to simply call ClientDataSet.Open, which will get the data from the DataSetProvider.
BTW, the default behavior of the DataSetProvider when you call the ClientDataSet.ApplyUpdates method is to send a SQL query to the connection object, and not the DataSet from which the data was obtained (assuming a homogeneous query). Make sure that your DataSetProvider.ResolveToDataSet property is not set to true.
Finally, on an unrelated note, your code above appears to be open to a SQL injection attack (though I have not tested this). It is safer to use a parameter to define the WHERE clause. If someone enters the following into Edit1 you might be in trouble (assuming the InterBase uses the drop table syntax): 1;drop table employee;
Check the LiveMode property of the TIBDataSet.

Resources