Camunda custom insert queries - crud

While following this documentation and sample https://docs.camunda.org/manual/7.3/real-life/how-to/#process-engine-custom-queries-custom-mybatis-queries, could you please explain how we can execute insert queries? In the sample to list values they have used below method.
commandContext.getDbSqlSession().selectList("selectTasksForRegion", region, 0, 100);
However commandContext.getDbSqlSession().insert is a protected method, therefore I'm unable to get an insert query out of it. Appreciate any suggestions.

The DbEntityManager has an
insert
method. The insert and update is than managed by the DbSqlSession based on the
getPersistantState
of the DbEntity. You only have to provided the correspondig mappings which have
to be prefixed with insert and update. For example see the build-in
entities.

in the underlying MyBatis SqlSession object, you will find what you need. You just have to navigate one level deeper: commandContext.getDbSqlSession().getSqlSession()
The entire line looks like this:
commandContext.getDbSqlSession().getSqlSession().insert("insertStuff", stuff);
With insertStuff being the name of your custom query and stuff being the parameter object for that query.

Related

Cannot drop table created within same script

I have a script in which I create a temporary table, that I subsequently want to drop.
I simply create the table, fill it using a INSERT INTO statement, but when it comes to dropping it, the script fails stating that the table is in use.
From reading around it would seem to be caused by the transaction managment, but I'm a little confused.
Here is a little script that reproduces the issue:
CREATE TABLE SCRIPT_TEMP (
NAME VARCHAR(100) NOT NULL,
USERNAME VARCHAR(150) NOT NULL);
COMMIT WORK;
INSERT INTO SCRIPT_TEMP (NAME, USERNAME)
SELECT NAME, COALESCE(USERNAME, 'empty')
FROM SALESREPS;
COMMIT WORK;
DROP TABLE SCRIPT_TEMP;
COMMIT WORK;
Or, in order to be easily testable to anyone without a SALESREPS table, use this insert statement :o)
INSERT INTO SCRIPT_TEMP (NAME, USERNAME)
SELECT 'Name 1', 'Username 1'
FROM RDB$DATABASE;
COMMIT WORK;
I fail to see what still holds a reference to the SCRIPT_TEMP table by the time the drop call is made. Why would the script's own transaction block it even after the second COMMIT?
If I split the execution in 2 scripts everything is fine.
What am I missing??
Thanks!!
PS: using Firebird 2.5.2, in case that matters
PPS: my script is a bit more involved than this. THe temp table is filled with table names and related constraints that need to be manipulated, but that's not the issue, that part is working well. And the fact is, the issue I want to resolve is easily reproducible with the code sample here, that I got to while debugging. This SO question seems to be about the exact same problem, but the only answer is not helpful to the problem itself
Thanks to Val Marinov for pointing me in the right direction.
It appears my issue is due to my SQL Manager - there must be a setting I'm not aware of.
Script runs as expected in FlameRobin.

Is there any way to safely run SELECT INTO?

I have a script that runs a SELECT INTO into a table. To my knowledge, there are no other procedures that might be concurrently referencing/modifying this table. Once in awhile, however, I get the following error:
Schema changed after the target table was created. Rerun the Select
Into query.
What can cause this error and how do I avoid it?
I did some googling, and this link suggests that SELECT INTO cannot be used safely without some crazy try-catch-retry logic. Is this really the case?
I'm using SQLServer 2012.
Unless you really don't know the fields and data types in advance, I'd recommend first creating the table, then adding the data with an Insert statement. In your link, David Moutray suggests the same thing, here's his example code verbatim:
CREATE TABLE #TempTableY (ParticipantID INT NOT NULL);
INSERT #TempTableY (ParticipantID)
SELECT ParticipantID
FROM TableX;

Updating a table which was created by a 'AS select' command

I have created a table using a 'AS SELECT' statement.
CREATE TABLE TEST AS
SELECT ...
from (MANY TABLES)
WHERE (MANY CONDITIONS);
How do I make sure that updates on any of the table columns go onto TEST as well?
Or do I have to use a VIEW? (which I dont want to as there is a need of a trigger to be working on TEST)
Are any other options available other than using a VIEW ?
You need to create a View.
CREATE TABLE AS SELECT just make a copy of data at the moment of execution.
Look into creating the table test as a materialized view.
Triggers can be placed on these and there are various update options too.
Depending on your database system you could use a Trigger to insert the values in the other table as well. That's if you need something like near-realtime syncronization. Or you might go for a daily/weekly/... batch synchronization.
As I am not so familiar with Oracle you should look at their documentation for a detailed description.

Force SQL Server column to a specific value

Is it possible to force a column in a SQL Server 2005 table to a certain value regardless of the value used in an insert or update statement is? Basically, there is a bug in an application that I don't have access to that is trying to insert a date of 1/1/0001 into a datetime column. This is producing a SqlDateTime overflow exception. Since this column isn't even used for anything, I'd like to somehow update the constraints on the columns or something in the database to avoid the error. This is obviously just a temporary emergency patch to avoid the problem... Ideas welcome...
How is the value being inserted? If it's through a stored proc... you could just modify the Sproc to ignore that input parameter.
if it's through client-side generated SQL, or an ORM tool, otoh, then afaik, the only option is a "Before" Trigger that "replaces" the value with an acceptable one...
If you're using SQL 2005 you can create an INSTEAD OF trigger.
The code in this trigger wil run in stead of the original insert/update
-Edoode
I'd create a trigger to check and change the value
If it is a third party application then I will assume you don't have access to the Stored Procedure, or logic used to generate and insert that value (it is still worth checking the SPs for the application's database though, to see if you can modify them).
As Charles suggested, if you don't have access to the source, then you need to have a trigger on the insert.
The Microsoft article here will give you some in depth information on creating triggers.
However, SQL Server doesn't have a true 'before insert' trigger (to my knowledge), so you need to try INSTEAD OF. Have a look here for more information. In that article, pay particular note of section 37.7, and the following example (again from that article):
CREATE TRIGGER T_InsertInventory ON CurrentInventory
INSTEAD OF INSERT AS
BEGIN
INSERT INTO Inventory (PartNumber, Description, QtyOnOrder, QtyInStock)
SELECT PartNumber, Description, QtyOnOrder, QtyInStock
FROM inserted
END
Nick.
the simplest hack would be to make it a varchar, and let it insert that as a string into the column.
The more complicated answer is, you can massage the data with a trigger, but it would still have to be valid in the first place. For instance I can reset a fields value in an update/insert trigger, but it would still have to get through the insert first.

Is it possible in SQL Server to create a function which could handle a sequence?

We are looking at various options in porting our persistence layer from Oracle to another database and one that we are looking at is MS SQL. However we use Oracle sequences throughout the code and because of this it seems moving will be a headache. I understand about #identity but that would be a massive overhaul of the persistence code.
Is it possible in SQL Server to create a function which could handle a sequence?
That depends on your current use of sequences in Oracle. Typically a sequence is read in the Insert trigger.
From your question I guess that it is the persistence layer that generates the sequence before inserting into the database (including the new pk)
In MSSQL, you can combine SQL statements with ';', so to retrieve the identity column of the newly created record, use INSERT INTO ... ; SELECT SCOPE_IDENTITY()
Thus the command to insert a record return a recordset with a single row and a single column containing the value of the identity column.
You can of course turn this approach around, and create Sequence tables (similar to the dual table in Oracle), in something like this:
INSERT INTO SequenceTable (dummy) VALUES ('X');
SELECT #ID = SCOPE_IDENTITY();
INSERT INTO RealTable (ID, datacolumns) VALUES (#ID, #data1, #data2, ...)
I did this last year on a project. Basically, I just created a table with the name of the sequence, current value, & increment amount.
Then I created a 4 procs :
GetCurrentSequence( sequenceName)
GetNextSequence( sequenceName)
CreateSequence( sequenceName, startValue, incrementAmount)
DeleteSequence( sequenceName)
But there is a limitation you may not appreciate; functions cannot have side effects. So you could create a function for GetCurrentSequence(...), but GetNextSequence(...) would need to be a proc, since you will probably want to increment the current sequence value. However, if it's a proc, you won't be able to use it directly in your insert statements.
So instead of
insert into mytable(id, ....) values( GetNextSequence('MySequence'), ....);
Instead you will need to break it up over 2 lines;
declare #newID int;
exec #newID = GetNextSequence 'MySequence';
insert into mytable(id, ....) values(#newID, ....);
Also, SQL Server doesn't have any mechanism that can do something like
MySequence.Current
or
MySequence.Next
Hopefully, somebody will tell me I am incorrect with the above limitations, but I'm pretty sure they are accurate.
Good luck.
If you have a lot of code, you're going to want to do a massive overhaul of the code anyway; what works well in Oracle is not always going to work well in MSSQL. If you have a lot of cursors, for instance, while you could convert them line for line to MSSQL, you're not going to get good performance.
In short, this is not an easy undertaking.