How to retrieve the auto incremented ID using slick / plainSQL? - sql

Isn't there a slick/plainSQL native solution to retrieve the auto incremented id of the current INSERT?
userId is an auto incremental field in my mySQL table.
sql"""
INSERT INTO `table`(`email`)
OUTPUT INSERTED.userId
VALUES ("theEmailAdress#test.de")
""".as[Int].firstOption
Help would be greatly appreciated.
Cheers
Oliver

Depends on the database.
For MS SQL it's SCOPE_IDENTITY(), for mySQL it's LAST_INSERT_ID().
Try searching for equivalent for your DB if it's none of the above.
Added by cvogt:
There is currently no slick-built-in feature for plain SQL for this and no way to access the underlying jdbc statement when using Slick's sql"..." interpolation or StaticQuery, which would allow you to access getGeneratedKeys. You could probably patch the SQL interpolator and StatementInvoker to allow this. They are just 150 LOC. Maybe worth giving a shot and submitting a PR.
You could however use one of the Slick session method like withPreparedInsertStatement, which wrap jdbc connection methods to work with a jdbc statement. I created a PR to add documentation about this: https://github.com/slick/slick/pull/691

Thank you cvogt for helping out in this discussion.
I think it would be helpful to submit a PR, inasmuch as it is a very common and useful functionality which should not be missing in slick's plainSQL queries.
Finally, i found a work-around to replace the missing native function as following.
Within the same session I settle two queries. The first one is the INSERT statement, the second statement is SELECT LAST_INSERT_ID() which returns the newest automatically generated value that was set for the AUTO_INCREMENT column by the recently executed INSERT(1). More details here: MySQL Reference - LAST_INSERT_ID()
Database.forDataSource(dataSource).withDynSession {
sqlu"""INSERT INTO `users`(`email`) VALUES ("theEmailAdress#test.de")
""".firstOption match {
case Some(num) if num == 1 => sql"SELECT LAST_INSERT_ID()".as[Long].firstOption()
case None => None
}
}
This works for me right now. If there are any improvements, do not hesitate to post your solution.

Related

Oracle Sql - Time based sql injection

When trying to do an SQL injection on an Oracle SQL database I have the problem that most of the examples in the tutorials do not work. I already found out that I only can use CASE WHEN a THEN b ELSE c END instead of normal if statements.
The question I have now is how do I get time delay into the injection? Benchmark() and sleep() do not work either.
I already now that the table is named "flag" and the field name I want to read out is named "password".
My only information i get from the database is the time it needed to execute my input (or query since I bypass the input to inject SQL)
I found the following SQL statement on the web at SQL Injection Tutorial
select dbms_pipe.receive_message(('a'),10) from dual;
I am not certain I should be participating in this sort of thing, but since I found it with my first Google Search, I will go ahead and post it.
I tested it and it delayed the result by 10 seconds.

Pentaho kettle : Below delete doesnt seem to work in SQL script

Ive tried to execute below delete through SQL script in Pentaho Job, I get the error as
Unknown table 'a' in MULTI DELETE. Can somebody throw light on this. Is there any other way
to go around this?
DELETE a.* FROM pm_report.PM_CONCERTS_GQV_REPORT_TEST a
WHERE EXISTS
(SELECT 1 FROM pm_report.PM_CONCERTS_GQV_REPORT_TEST_3 b WHERE b.TM_EVENT_ID=a.TM_EVENT_ID
GROUP BY b.TM_EVENT_ID)
This is mysql right?
See similar solutions here - recommends removing the table alias.
Worth noting this is nothing to do with Pentaho, if you did it in a SQL client you'd get the same error. If you don't then the difference is probably in the jdbc driver version - may be worth checking that.
i can suggest these options:
dont use aliases
try this directly on your mysql and check if it works for you.
dont use pentaho like this : make a transformation and break apart the query to steps
with table input and lookup then delete the rows by row_id
its a little bit longer but a lot more undersrandable and easy to maintain.
"dont over optimize"

Does using regular expressions in a SQL Select statement change real data?

select orderid from orders where REGEXP_REPLACE(orderid,'/^0+(.)/')
I have searched the documentation and am missing it. If I run this query will it change any real data or just my set returned for output (the "virtual" data)? The word replace scares me. I am using oracle 11g.
Thank you.
Because you are performing a SELECT, you end up getting a read only view of the data, nothing has changed.
So you don't need to worry about running this select statement. The only way to update it would be to follow this up with an UPDATE command.
No, it doesn't. (even though this answer is too short for SO).

sql - check to see if an entry exists, if so update,is if not insert

I was wondering if there was a way that I can do the folloing in one sql statement.
I am parsing an csv file for product insertion into the database. is there a way that I can check to see if an entry in a table with X equaling to N, if so update the rest f the columns else insert it?
regards
Phil
This type of operation is sometimes called an "UPSERT". The SQL standard way to do it is to use the MERGE statement, but unfortunately it is not widely implemented yet.
Some databases have added their own ways to do it, such as the non-standard MySQL extensions REPLACE and INSERT ... ON DUPLICATE KEY UPDATE.
The MERGE statement will get you there, but it's only available on SQL Server 2008 R2. You would otherwise need to treat this as a Slowly Changing Dimension and either bring the data into a temp table and compare or use an integration services package to do the work.
Would something like this work for you?
if(update myTable where x='n')
else{
insert into myTable(x,y,z) values(1,2,3)
}
The update query will run regardless, and will return false if it couldn't update that record, causing it to do the insert.

INSERT vs INSERT INTO

I have been working with T-SQL in MS SQL for some time now and somehow whenever I have to insert data into a table I tend to use syntax:
INSERT INTO myTable <something here>
I understand that keyword INTO is optional here and I do not have to use it but somehow it grew into habit in my case.
My question is:
Are there any implications of using INSERT syntax versus INSERT INTO?
Which one complies fully with the standard?
Are they both valid in other implementations of SQL standard?
INSERT INTO is the standard. Even though INTO is optional in most implementations, it's required in a few, so it's a good idea to include it if you want your code to be portable.
You can find links to several versions of the SQL standard here. I found an HTML version of an older standard here.
They are the same thing, INTO is completely optional in T-SQL (other SQL dialects may differ).
Contrary to the other answers, I think it impairs readability to use INTO.
I think it is a conceptional thing: In my perception, I am not inserting a row into a table named "Customer", but I am inserting a Customer. (This is connected to the fact that I use to name my tables in singular, not plural).
If you follow the first concept, INSERT INTO Customer would most likely "feel right" for you.
If you follow the second concept, it would most likely be INSERT Customer for you.
It may be optional in mySQL, but it is mandatory in some other DBMSs, for example Oracle. So SQL will be more potentially portable with the INTO keyword, for what it's worth.
In SQL Server 2005, you could have something in between INSERT and INTO like this:
INSERT top(5) INTO tTable1 SELECT * FROM tTable2;
Though it works without the INTO, I prefer using INTO for readability.
One lesson I leaned about this issue is that you should always keep it consistent! If you use INSERT INTO, don't use INSERT as well. If you don't do it, some programmers may ask the same question again.
Here is my another related example case: I had a chance to update a very very long stored procedure in MS SQL 2005. The problem is that too many data were inserted to a result table. I had to find out where the data came from. I tried to find out where new records were added. At the beginning section of SP, I saw several INSERT INTOs. Then I tried to find "INSERT INTO" and updated them, but I missed one place where only "INSERT" was used. That one actually inserted 4k+ rows of empty data in some columns! Of course, I should just search for INSERT. However, that happened to me. I blame the previous programmer IDIOT:):)
They both do the same thing. INTO is optional (in SQL Server's T-SQL) but aids readability.
I started wtiting SQL on ORACLE, so when I see code without INTO it just looks 'broken' and confusing.
Yes, it is just my opinion, and I'm not saying you should always use INTO. But it you don't you should be aware that many other people will probably think the same thing, especially if they haven't started scripting with newer implementations.
With SQL I think it's also very important to realise that you ARE adding a ROW to a TABLE, and not working with objects. I think it would be unhelpful to a new developer to think of SQL table rows/entries as objects. Again, just me opinion.
INSERT INTO is SQL standard while INSERT without INTO is not SQL standard.
I experimented them on SQL Server, MySQL, PostgreSQL and SQLite as shown below.
Database
INSERT INTO
INSERT
SQL Server
Possible
Possible
MySQL
Possible
Possible
PostgreSQL
Possible
Impossible
SQLite
Possible
Impossible
In addition, I also experimented DELETE FROM and DELETE without FROM on SQL Server, MySQL, PostgreSQL and SQLite as shown below:
Database
DELETE FROM
DELETE
SQL Server
Possible
Possible
MySQL
Possible
Impossible
PostgreSQL
Possible
Impossible
SQLite
Possible
Impossible
I prefer using it. It maintains the same syntax delineation feel and readability as other parts of the SQL language, like group BY, order BY.
If available use the standard function. Not that you ever need portability for your particular database, but chances are you need portability for your SQL knowledge.
A particular nasty T-SQL example is the use of isnull, use coalesce!