Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does the extension method InsertGetId works for Oracle? #465

Open
frenkhub opened this issue Apr 12, 2021 · 5 comments
Open

Does the extension method InsertGetId works for Oracle? #465

frenkhub opened this issue Apr 12, 2021 · 5 comments

Comments

@frenkhub
Copy link

Hello, thanks for developing this project.

Does the extension method InsertGetId works for Oracle?

@ahmad-moussawi
Copy link
Contributor

I don't think so, could you provide what is the correct way to fetch the last inserted id in Oracle so we can implement it

@frenkhub
Copy link
Author

Sorry I'm not an expert of Oracle but at the moment when I call the method InsertGetId with an Oracle database it returns an exception "The sequence is empty", by the way the row is inserted. After looking the code it seems not implemented for the Oracle compiler. Why not returning a NotImplementedException istead in this case with a message?

I searched a bit now for a possible solution, I found https://oracle-base.com/articles/misc/dml-returning-into-clause. I tried it with the SqlDeveloper and seems working. The only problem seems that it is necessary tell the OracleCompiler what is the name of the autogenerated column (In my case "Id"). This is my try:

SET SERVEROUTPUT ON
DECLARE
last_generated_id "Team"."Id"%TYPE;
BEGIN
INSERT INTO "Team" ("Name", "Balance", "EnemyTeamId", "History") VALUES ('JUVENTUS', 123.34, null, 'a long history for this club')
RETURNING "Id" INTO last_generated_id;
COMMIT;

DBMS_OUTPUT.put_line(last_generated_id);
END;

@ahmad-moussawi
Copy link
Contributor

Actually the Oracle support is a bit struggling, since we don't have a ready environment for Oracle, throwing NotImplementedException and mentioning that in the docs is the way to go in the short term.

I will keep this open, since we need more research to evaluate what is the best way for different Oracle versions.

@JordanMarr
Copy link

JordanMarr commented Feb 21, 2022

Hi Ahmad,

I am currently implementing Oracle support in my data library (which uses SqlKata) and today I confirmed that appending the following to my INSERT command does indeed work for Oracle:

var identityField = "REGION_ID";

// Append Oracle identity query + output parameter
cmd.CommandText = cmd.CommandText + $" returning \"{identityField}\" into :outputParam";
var outputParam = cmd.CreateParameter();
outputParam.ParameterName = "outputParam";
outputParam.DbType = System.Data.DbType.Decimal;
outputParam.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(outputParam);
await cmd.ExecuteNonQueryAsync();
var returnId = System.Convert.ChangeType(outputParam.Value, typeof(int));

Oracle table definition:

CREATE TABLE regions
  (
    region_id NUMBER(10,0) GENERATED BY DEFAULT AS IDENTITY
    START WITH 5 PRIMARY KEY,
    region_name VARCHAR2(50) NOT NULL
  );

It's a little different from SQL Server in that you must use an output parameter + ExecuteNonQueryAsync instead of using ExecuteScalarAsync as you do in SQL Server. Also it does require the name of the identity column.

@JordanMarr
Copy link

Also, if you are using Docker for your test databases, I would be happy to contribute the custom Oracle docker image that I am in the process of tweaking now for Oracle development in my project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants