Insert by reference in MySQL - mysql

In Oracle Database (SQL Plus), there is an alternative method to insert values into a table, which my lecturers called "insert by reference". It looks like this:
SQL> INSERT INTO table_name ('&col_name1','&col_name2' ...);
Enter value for col_name1: value1
Enter value for col_name1: value1
...
This enables you to use the same command repeatedly (by pressing up arrow) to enter multiple records in the table; you only need to enter the specific values separately after executing the command. And there is no need to go back to each value, erase it and type in the new value.
So my question is, is there any way to replicate this handy command in MySQL?

This is a feature of sqlplus, not of oracle's, taking advantage of oracle's prepared statement feature.
You need to find or develop an sql client for mysql that can similarly use mysql's prepared statement feature in a nicer way either directly through SQL or through an API (C API is just an example).
We cannot recommend 3rd party tools or utilities here on SO, you need to find the one that best suits your needs.

perhaps use the multi row insert:
insert into table_name (col_name1, col_name2)
values (value_1_1, value_1_2), (value_2_1, value_2_2) [...]

Related

Update\Insert data from grafana to mysql

Is is possible to update data or insert data from grafana to mysql. I have a requirement to insert/update information in mysql using a UI. Now I am already using grafana so wanted to know if there is any way we can use grafana to update or insert information
There is no input panel for taking user input and inserting that data to MySQL or any other. (Grafana v7.0)
For very minimalist input data you can use grafana variables as a hack.
Create example table for storing input in MySQL
CREATE TABLE `grafana_variable` (`variable` VARCHAR(64)) ENGINE = InnoDb;
In Grafana dashboard click settings icon:
then click:
add variable:
return to dashboard and you should see at the top:
create a new visualization panel or add another query in any already existing panel and add SQL query:
INSERT INTO `grafana_variable` VALUES ('${myvar}');
now every time you type into that field
and click away from it or use ie tab key the data will be inserted to the MySQL database.
mysql> select * from grafana_variable;
+---------------------+
| variable |
+---------------------+
| this is just a test |
+---------------------+
1 row in set (0.08 sec)
The downside of this hack is that the visualization tile will have in its upper left corner error icon:
with information (when you hover over it):
Found no column named time or time_sec
because the sql query of the visualization tile is inserting data instead of selecting it from database therefore there is no time or time_sec data.
Grafana also does not handle multiple MySQL statements so you cannot repair that by adding before or after the INSERT INTO ... statement second one with SELECT FROM. Maybe this could be somehow patched by using sub queries or something similar but I did not investigate that further.
Because the error as above can be due to multiple reasons not related to the hack it will be better to use the hack query in separate visualization tile - the one that you will remember (or even give descriptive panel tile) so you know that the error there is nothing unusual.
See grafana varialbes for more info about variables.
There is also useful list of already existing variables you can use same way as myvar I created. See section MACROS here For eg:
$__timeFrom()
and
$__timeTo()
have the start and the end of displayed time range.
Permissions and Security
The whole hack works because the MySQL user that grafana uses is allowed to execute INSERT statement, but if grafana is able to execute ANY statement then make sure that MySQL user that grafana uses is not allowed for example to execute statements like DROP ... or any other that is not related to INSERT data into the grafana_variable table as in example.
If you use MySQL as datasource for displaying data the grafana user should also be able to execute SELECT statements.
But nothing else than that.
Read about MySQL user premissions
Must hide Update as temporary table
I am working with postgres and Grafana. Probably it is quite similar.
With postgres you have to hide the update like this:
WITH UPDAT_TEMP AS (UPDATE MyTable SET MY_ROW='MY_TEXT' WHERE ID=99)
SELECT 1;
If you want to update various rows, you have to put various temporary tables.
The
Update my_table (rows) values(...)
does not work for me under Grafana.
Therefore:
WITH UPDAT_TEMP AS (UPDATE MyTable SET MY_ROW='MY_TEXT' WHERE ID=99),
WITH UPDAT_TEMP2 AS (UPDATE MyTable SET MY_ROW2='MY_TEXT2' WHERE ID=99)
SELECT 1;

MySQL "INSERT" and SQL injection

I have this simple mysql query:
INSERT INTO table (col1, col2) VALUES ('1', '2')
col1 and col2 are foreign keys for another table so any value for col1 and col2 must be present in the other table or otherwise the row won't be inserted.
Is there still any risk of SQL injection in this case? If i receive these col values from PHP POST, do I still need to bind them before insertion into the database or they are already secure as the cols are foreign keys?
Yes. All input from users needs to be check for sanitized. E.g. if a user is sending you a string like that '2'); drop table <table> as your second value it might get executed and giving you some surprise. (String might not work exactly, but I think you got the point)
It's indeed prone to SQL Injection, since the user could, for example, break your query and get information about your RDBMS and your database schema in the error message, and use it to prepare another attacks to your applications.
There are a lot of ways to explore SQL Injection issue.
Yes, there is always a risk of injection, even with foreign key constraints. If I know what is a valid col1 and col2 value, I can use those values to construct an attack. It is best to always scrub user input and assume the user is trying to hurt your database.
When constructing database queries in PHP, use an interface that allows you to use placeholders for your data that will handle any escaping automatically. For example, your query would look like:
INSERT INTO table (col1, col2) VALUES (:col1, :col2)
Then you can bind against that using the appropriate method in a driver like PDO. If you're disciplined about using placeholders for user data, the chance of a SQL injection bug occurring is very low.
There's a number of ways to properly escape user input, but you must be sure to use them on all user data, no exceptions. A single mistake can be sufficient to crack your site wide open.

SQL Server implementation of MySQL's "new" functionality?

MySQL has this incredibly useful yet proprietary record holding the "new row"(NEW).
I wonder if there is any SQL server command to replace the New in MySQL.
In mysql, in a trigger, I would use something like this.
INSERT INTO products(idProduct,idReference,date)
VALUES (NEW.idProduct,idReference,NOW());
However I don't know how if is it possible to do the same command but in Sql Server.
I hope I have been clear in my question.
If not explicit, or if it isn't possible to implement what I want, I apologize.
Thank you all.
In your trigger
INSERT products(idProduct,idReference,date)
SELECT idProduct, idReference, GETDATE()
FROM inserted
new is only available in a trigger if I'm not mistaken.
As SQL Server uses statement-level triggers and MySQL uses row-level triggers there is not direct equivalent to the concept of "the new row" in a trigger. Read the documentation on the inserted virtual table that is available in SQL Server.
Example usage: SQL Insert trigger to update INSERTED table values

Using MySQL without any procedures or functions

Is it possible to use any sort of logic in MySQL without using any procedures? My web hosting does not let me create any procedures so I'm looking for a workaround.
The type of thing I want to do is only add an item to a table if it doesn't already exist. Or add a column to a table if it's not already there. There are some operations that can be done such as CREATE TABLE IF NOT EXISTS and so on, but some operations I require do not have such luxuries :(
I realised late on that my lovely procs won't work and so I tried writing IF/ELSE logic as top-level queries, but for MySQL, IF ELSE blocks only seem to work inside functions/procs and not at the global scope.
Any workarounds greatfully received - I've already asked the hosting to grant me privileges to create procedures but no reply as yet...
I suppose you don't have access to the INFORMATION_SCHEMA either. You can possibly find solutions but it would be better, in my oninion, to:
Change your hosting provider. Seriously. Pay more - if needed - for a MySQL instance that you can configure to your needs. You only have a crippled DBMS if you are not allowed to create procedures and functions.
Posible workarounds for the specific task: You want to add a column if it doesn't exist.
1) Just ALTER TABLE and add the column. If it already exists, you'll get an error. You can catch that error, in your application.
2) (If you have no access to the INFORMATION_SCHEMA) maintain a version of the schema, for your database.
The best solution that I can think of would be to use an additional language with SQL. For example, you can run a query for a specific record, and based on the response that you get, you can conditionally run an INSERT statement.
For inserting a table if it doesn't exist, try using the SHOW TABLES statement and testing whether or not a name exists in the result set.
MySQL supports INSERT IGNORE. and INSERT ... ON DUPLICATE KEY UPDATE.
The following will insert a new row, but only if there is no existing row with id=10. (This assumes that id is defined as a unique or primary key).
INSERT IGNORE INTO my_table (id, col1, col2) values (10, "abc", "def");
The following will insert a new row, but if there is an existing row with id=10 (again, assuming id is unique or primary), the existing row will be updated to hold the new values, instead of inserting a new row.
INSERT INTO my_table (id, col1, col2) values (10, "abc", "def")
ON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2)
Also, CREATE TABLE supports the IF NOT EXISTS modifier. So you can do something like:
CREATE TABLE IF NOT EXISTS my_table ...
There are many other similar options and modifiers available in MySQL. Check the docs for more.
Originally I created a big script to create or update the database schema, to make it easier to deploy database changes from my local machine to the server.
My script was doing a lot of "if table 'abc' exists and it doesn't have a FK constraint called 'blah'" then create an FK constraint called 'blah' on table 'abc'... and so on.
I now realise it's not actually necessary to check whether a table has a certain column or constraint etc, because I can just maintain a schema-versioning system, and query the DB schema-version when my app starts, or when I navigate to a certain page.
e.g. let's say I want to add a new column to a table. It works like this:
Add a new migration script to the app code, containing the SQL required to add the column to the existing table
Increment the app's schema-version by 1
On app startup, the app queries the DB for the DB's schema-version
If DB schema-version < app schema-version, execute the SQL migration scripts between the two schema-versions, and then update the DB schema-version to be the same as the app
e.g. if the DB's schema-version is 5 and the app version is 8, the app will apply migration scripts 5-6, 6-7 and 7-8 to the DB. These can just be run without having to check anything on the DB side.
The app is therefore solely responsible for updating the DB schema and there's no need for me to ever have to execute schema change scripts on the local or remote DB.
I think it's a better system than the one I was trying to implement for my question.

Which would be faster....many insert single value statements or an insert statament with many values?

Which will be faster in execution among the following cases? (It is required to decide appropriate approach in my project)
insert into table values (v1, v2, v3);
or
insert into table1 value (v1)
insert into table1 value (v2)
insert into table1 value (v3)
what are your opinions?
Not my opinion; but from experience doing something in one query rather than multiple ones to achieve the same thing is always faster.
If you're using batching properly it shouldn't make a huge difference. The first would be faster however.
The approach 1 would be faster than the approach 2 , because of following reasons
1.Less network calls
2.Less Compilation/Parsing/Explain Plan/ in DB
Regards
Abhi
I think your syntax is wrong. If you're trying to insert multiple rows with one insert, your query would look more like this:
INSERT INTO table1 VALUES (v1), (v2), (v3)
And executing with one query is always faster than multiple queries (that do the same thing).
The (v1, v2, v3) version will be faster, but be careful how best to do this in your driver. In Java, you'd use a simple INSERT INTO table VALUES (?) PreparedStatement, and use addBatch() to combine them into a single larger statement that is executed with executeBatch().
See section 3.4:
http://java.sun.com/developer/Books/JDBCTutorial/
You would also need to enable the rewriteBatchedStatements property in the Connector/J driver:
http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-configuration-properties.html
LOAD DATA INFILE will be faster still if that works for your application.