Parametrized query with MySQL executed atomically with SELECT using ADO.NET - mysql

I am using ADO.NET and Parametrized Queries (unnamed parameters and ExecuteNonQuery method) to write to both SQL Server and MySQL dBases (the application has to work agnostically with both). With both, the primary keys of all tables are auto-incrementing.
With SQL Server I am able to set "CommandText" to the following in which case the parametrized query and the SELECT execute in an atomic fashion:
INSERT INTO myTable (param1, param2, param3) VALUES (?, ?, ?);SELECT MAX(ID) FROM myTable;
This ensures that the ID (primary key) that is returned is the one corresponding to the parametrized query.
Unfortunately, with MySQL the ";SELECT..." generates a syntax error. How can I execute a parametrized query atomically with a SELECT query using ADO.NET and MySQL?
Thanks in advance for your help!

Thanks a lot for everyone's help! As per everyone's suggestion I am no longer using Select Max(ID).
Instead with SQL Server I am adding an OUTPUT clause in the INSERT statement as suggested here:
How do I use an INSERT statement's OUTPUT clause to get the identity value?
With MySQL I am using select last_insert_id() as suggested. It works!

Related

SQL insert query inside select or where clause

Maybe my question above may be could be stupid , but I just want to know if is it possible to have insert query inside select or where.
The reason that I want to know that is if someone hack website or any application database, can the hacker input data to hacked database without my knowledge ?
the following example of SQL injection I see in other sites
http://www.example.com/empsummary.php?id=1 AND 1=-1 union select 1,group_concat(name,0x3a,email,0x3a,phone,0x2a),3,4,5,6,7,8,9 from employee
I know what exactly that above query does, but can the hacker input (use insert query) on the database or on any table ?
Yes, it can happen, if the database interface is configured to allow multiple statements in a query.
An INSERT can't run as part of a SELECT statement. But it's possible that the exploit of a vulnerability could finish a SELECT and then execute a separate insert.
Say you have a vulnerable statement like this:
SELECT foo FROM bar WHERE fee = '$var'
Consider the SQL text when $var contains:
1'; INSERT INTO emp (id) VALUES (999); --
The SQL text could be something like this:
SELECT foo FROM bar WHERE fee = '1'; INSERT INTO emp (id) VALUES (999); --'
If multi-statement queries are enabled in the database interface library, it's conceivable that an INSERT statement could be executed.
See: https://www.owasp.org/index.php/SQL_Injection

How do I run transactions in CakePHP3 while retrieving last insert id and work for both PostgreSQL and MySQL?

I am using CakePHP 3.x
There is a way to execute transactions in CakePHP 3.x.
However, some of my execute statements require the id of the previous insert statements.
How do I perform that in a transaction while choosing CakePHP 3.x and allowing either PostgreSQL or MySQL as my database?
My expected query is like this:
INSERT INTO dynamic_views (`title`, `created`) values ('view 37', NOW());
-- take the id of the above insert query and assuming the view id is 37
INSERT INTO users_access_dynamic_views(user_id, view_id) values (44, 37);
I would like to perform the above using transaction using CakePHP3.x.
At the same time, I would like to ask if using transaction for the above situation is it considered a bad idea?
After executing an insert query, you can call lastInsertId() with the right arguments to get the correct value:
$connection->transactional(function ($connection) {
$statement = $connection->newQuery
->insert($fields)
->into($table)
->values($values)
->execute();
$insertId = $statement->lastInsertId($table, 'id'); // id is primary key
});
The function to get the last inserted id in MySQL is called last_insert_id(), while in PostgreSQL it is lastval(). So either you have to create some mapping between the two, or you have to check which driver you are using in CakePHP and then call the specific function.
For example, you can create the following function in PostgreSQL.
CREATE FUNCTION last_insert_id() RETURNS BIGINT AS $$
SELECT lastval();
$$ LANGUAGE sql VOLATILE;
Then you can call it in the second query and it will work both in MySQL and PostgreSQL.
INSERT INTO users_access_dynamic_views
(user_id, view_id)
VALUES
(44, LAST_INSERT_ID());
Mind also that PostgreSQL uses sequences to generate IDs, so relying simply on lastval might produce unexpected results when there are triggers involved (inserting data somewhere on their own). So, it is always better to specify the sequence involved explicitly through currval.
CURRVAL(PG_GET_SERIAL_SEQUENCE('dynamic_views', 'view_id'))

mysqli - how do I count the number of rows before an insert without PHP?

This is mostly an academic problem as I try to learn SQL better. Is there a way to do this in a single SQL statement, without first doing a row count, then another statement to insert?
Traditionally I'll do this:
SELECT COUNT(*) FROM mytable;
Then in PHP's result object I'll know the number of rows. let's say I call it $totalrows. Then I'll do
INSERT INTO mytable (`rows`) VALUES ($totalrows);
This of course requires separate queries and PHP.
I wonder if there is a way to accomplish the same using a single SQL statement? I'm using mysqli.
Of course:
INSERT INTO mytable (`rows`)
SELECT COUNT(*)
FROM mytable;

How to INSERT SQL statements INTO table

In MS Access, how do I insert a row which has one column that takes an SQL statement (SELECT) as value? In other words, how to I tell the SQL interpreter not to try to parse that statement and give me errors?
Wrap it in quotes like any other character.
INSERT INTO myTable
('MySQLColumn')
VALUES
('SELECT * FROM MyOtherTable')

How does the WITH statement store the record set for the select query?

Consider the following SQL (SQL Server 2008) statement:
WITH MyResult AS
(
SELECT
Name,
Row_ID AS ORD
FROM Person Where Gender = #Gender
)
SELECT *
FROM MyResult
WHERE ORD > 5
Is MyResult stored in a temporary table in the tempdb? Or does it do something else?
We are optimising some queries and would lke to better understand WITH statements (internally) to help gauge performance etc.
Thanks
No, as per this MSDN article
...the CTE is a language-level
construct—meaning that SQL Server does
not internally create temp or virtual
tables...
And also, as mentioned here:
A common table expression (CTE) can be
thought of as a temporary result set
that is defined within the execution
scope of a single SELECT, INSERT,
UPDATE, DELETE, or CREATE VIEW
statement. A CTE is similar to a
derived table in that it is not stored
as an object and lasts only for the
duration of the query.