I have a trigger that looks like below:
create trigger theTrig
insert on table_A referencing new as n
for each row(
execute procedure proc_A();
);
May I know how can I pass the new/old reference object into stored proc inside a trigger?
CREATE TRIGGER theTrig
INSERT ON table_A REFERENCING NEW AS n
FOR EACH ROW
(
EXECUTE PROCEDURE proc_A(n.col2, n.col3, n.col5, n.col7, n.col11);
);
I usually write 'REFERENCING NEW AS NEW' and/or 'REFERENCING OLD AS OLD' and Informix is quite happy to oblige with the tautologous specification.
Related
I'm trying to create a stored procedure to insert new records in a number of child tables (using Greenplum) I have a master table and a set of child tables. I would like to insert new records that I have in the master table into the child tables (I have around 20 child tables). My assumption is that I should create a function, then a trigger.
Note that I only want to insert some fields into the child tables.
I made a few attempts, but here's the last one: (sorry in advance if it looks very bad. I never created any trigger functions)
FUNCTION:
CREATE OR REPLACE FUNCTION
schema1.newcustomerdata() RETURNS trigger AS $new_customer_data$
BEGIN
INSERT INTO schema1.customeridentifiers
(customer_id,
date_time)
SELECT NEW.customer_id,
date_time
FROM schema1.customersmaster
;
RETURN NEW;
END;
$new_customer_data$ LANGUAGE plpgsql;
TRIGGER:
CREATE TRIGGER newcustomerdata
AFTER INSERT ON schema1.customersmaster
FOR EACH ROW EXECUTE PROCEDURE newcustomerdata();
The function and trigger runs. However, I can't insert data in the master table anymore.
I get this error message:
function cannot execute on segment because it issues a non-select statement
So my questions are:
What would be the best solutions to update the child tables?
What's wrong with my function or trigger?
What are your recommendations?
Apparently "Triggers are not supported since they typically rely on the use of VOLATILE functions" Use RULES instead of triggers
CREATE RULE newcustomerdata AS ON INSERT TO schema1.customersmaster
DO also INSERT INTO schema1.customeridentifiers VALUES (NEW.customer_id, NEW.date_time);
I have got an issue to retreive stored procedure result ( Table ) into a data table,
when i try to run my procedure from sql server , it's working, same as testing it from a dataset ( I have used a datatableadapter which invoque my stored procedure.
but when i try to get my stored procedure via code, it return an empty datatable.
here is what my query look like (it contain a lot of field so i tried to resume all,
CREATE TABLE #TemporaryTable(Code_Suivi smallint IDENTITY(1,1), DATECREATION date, NOMPROJET varchar(20), ProducedHours decimal(10,1), Accumulation)
insert into #TemporaryTable ( DATECREATION , NOMPROJET , ProducedHours )
SELECT query -- it will insert into #TemporaryTable what I have selected
to avoid getting an empty I have to not work with insert into... which is impossible for me, have any one encountered this befoure??
I have used another way to get it work, by avoiding datatable adapter, and using sqldatasource to invoque a select query
I want a simple SQL (trigger) for duplicate checking.
My table name is test1 with 2 columns, code and sname. Before inserting a new record, check if the record already exists: if it does, generate an error and do not insert; if it does not, let the insert proceed.
How do I do that?
The simplest, most reliable way to ensure that there is no duplicate data in the table is not using triggers at all, but using UNIQUE or PRIMARY KEY constraints:
CREATE TABLE test1
(
code INTEGER NOT NULL PRIMARY KEY,
sname VARCHAR(32) NOT NULL UNIQUE
);
The four constraints (two NOT NULL, one PRIMARY KEY, one UNIQUE) automatically ensure that no duplicate records are inserted into the table.
If you choose to add a trigger, it will be duplicating the work that is done by these constraints.
As to how to do it, you will need to create a stored procedure which is invoked from the trigger statement. It will be given the new code and new name, and will do a SELECT to see whether any matching record occurs, and will raise an exception if it does and will not raise an exception if not.
CREATE PROCEDURE trig_insert_test1(ncode INTEGER, nname VARCHAR(32))
DEFINE ocode INTEGER;
FOREACH SELECT code INTO ocode
FROM test1
WHERE code = ncode OR sname = nname
RAISE EXCEPTION -271, -100, "Value to be inserted already exists in table test1";
END FOREACH;
END PROCEDURE
Then you use:
CREATE TRIGGER ins_test1 INSERT ON test1
REFERENCING NEW AS NEW
FOR EACH ROW (EXECUTE PROCEDURE ins_trig_test1(new.code, new.sname))
In Informix 4GL, you can either create strings containing these statements, and then PREPARE and EXECUTE (and FREE) them, or you can use SQL blocks:
SQL
CREATE TRIGGER ins_test1 INSERT ON test1
REFERENCING NEW AS NEW
FOR EACH ROW (EXECUTE PROCEDURE ins_trig_test1(new.code, new.sname))
END SQL
But, as I said at the outset, using triggers for this is not the best way to go; it is redundant given the table definition.
I've not run any of the SQL or SPL past the server; you'll need to check that the semi-colons are in the right places in the SPL, as SPL is fussy about that.
You can find the syntax for the SQL and SPL statements in the Informix 11.70 Information Centre.
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?
Is it possible to write a stored procedure with dynamic parameters in sql server 2005
Technically no, but there's a workaround: temp tables. Create a temp table, then set up your stored procedure to read its configuration from the temp table.
Here's an example of how to call it:
CREATE TABLE #inputParams (ParamName VARCHAR(20), ParamValue VARCHAR(20))
INSERT INTO #inputParams (ParamName, ParamValue) VALUES ('First Name', 'John')
INSERT INTO #inputParams (ParamName, ParamValue) VALUES ('Last Name', 'Doe')
EXEC dbo.USP_MyStoredProcedure
and then inside your stored procedure, you could retrieve whatever parameters you needed by checking for the existence of that temp table, and querying the parameters from it like this:
CREATE PROCEDURE dbo.USP_MyStoredProcedure AS
DECLARE #FirstName VARCHAR(20)
SET #FirstName = SELECT ParamValue FROM #inputParams WHERE ParamName = 'First Name'
GO
That way, your stored procedure's number of parameters never changes, which makes it easier for some dev applications to call it over time, but this is reeeeeally dangerous. From the outside of the stored proc, you never have any idea what version of the stored proc you're calling, and whether or not it's going to do anything with the parameters you're sending in.
What you might think about instead is abstracting away your stored proc inside another stored proc as a wrapper.
No, both the count and parameter types are fixed as part of the stored procedure declaration.
If there's a discrete set of parameters you could pass them into the sproc as XML. Then you can shred the XML into variables inside the body of the sproc e.g.
CREATE PROCEDURE MyDynamicStoredProc
#ParameterXML XML
AS
SET NOCOUNT ON
DECLARE #Parameter1 NVARCHAR(50)
DECLARE #Parameter2 INT
SET #Parameter1 = #ParameterXML.value('/Root/Parameters/StringParameter/#Value','nvarchar(50)')
SET #Parameter2 = #ParameterXML.value('/Root/Parameters/IntegerParameter/#Value','int')
...
NB: My XQuery-fu is weak, don't rely on this example!