I'm trying to write sql to insert a SQL code into one of the table's columns.
The table has these three columns: email, verification code, sql.
I try this code, and variations of it, playing around with the quotes and backslashing/escaping them, etc... but something's still wrong:
INSERT INTO pre_registration(email, verification_code, sql) VALUES('myemail#gmail.com', '8efb100a295c0c690931222ff4467bb8', '"INSERT INTO customer(title) VALUES(\'Mr.\')"')
It tells me there's an error in the SQL syntax:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'sql) VALUES('myemail#gmail.com', '89f0fd5c927d466d6ec9a21b9ac34ffa', "INSER' at line 1
How to do it? I'm using PHP/MySQL.
MySQL considers sql as a keyword. You have to quote it:
INSERT INTO pre_registration(email, verification_code, `sql`) VALUES('myemail#gmail.com', '8efb100a295c0c690931222ff4467bb8', '"INSERT INTO customer(title) VALUES(\'Mr.\')"')
By the way double the quotes to escape them instead of using bakslashes. This is more SQL friendly.
INSERT INTO pre_registration(email, verification_code, `sql`) VALUES('myemail#gmail.com', '8efb100a295c0c690931222ff4467bb8', '"INSERT INTO customer(title) VALUES(''Mr.'')"')
Some insight into the exact SQL error would help. At first glance I'd say you need to apply spaces between the table name and the open parentheses and between values and the open parentheses.
Also, the Single quotes around the double quotes for the SQL portion may be creating an error though I am not certain. Whatever is between the single quotes is interpreted literally which should make the escape characters actually be slashes inside the stored data.
Also, sql is a reserved word that must be quoted for use.
Finally, depending on your situation there may be a more secure method of data entry using prepare and bound parameters:
try
{
$conn = new PDO ( "sqlsrv:server = $serverstringname; Database = $logindatabase", "$loginusername", "$loginpassword");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch ( PDOException $e )
{
print( "Error connecting to SQL Server." );
die(print_r($e));
}
$email = 'myemail#gmail.com' //or some other way of setting the variable like $_POST
$verification_code = '#####' //or $_Post method
$sql = 'Put Query Here' //probably have to declare this explicitly
$sql_insert = "INSERT INTO pre_registration_info (email, verification_code, 'sql') VALUES (?,?,?)";
$stmt = $conn->prepare($sql_insert);
$stmt->bindValue(1, $email);
$stmt->bindValue(2, $verification_code);
$stmt->bindValue(3, $sql);
$stmt->execute();
Related
I'm using hibernate and mysql
when I run the following statement in mysql it works perfectly:
INSERT INTO table1 (name, is_visited) VALUES ('visit our site \'n\' days',true);
However, When I run with hibernate native query I get error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'days',true)' at line 1.
Here is the java code:
String query = "INSERT INTO table1 (name, is_visited) VALUES ('visit our site \'n\' days',true)";
Query nativeQuery = getEntityManager().createNativeQuery(query);
nativeQuery.executeUpdate();
When I change the query statement to
"INSERT INTO table1 (name, is_visited) VALUES ('visit our site \'n days',true)";
it works.
looks like there is an issue with \'n\'
any idea?
What is happening here is that the following query is correctly escaping the single quotes when run directly on MySQL:
INSERT INTO table1 (name, is_visited) VALUES ('visit our site \'n\' days', true);
This works on MySQL because one valid way to escape literal quotes on MySQL is to escape them with backslash. However, doing this inside a Java string means that the \' are not being passed to MySQL. Instead, Java consumes the single backslash, and just the single quotes make it across to the database. I suggest using the other method of escaping single quotes here, which is to double them up:
String query = "INSERT INTO table1 (name, is_visited) VALUES ('visit our site ''n''x days', true)";
While it might be possible to escape the backslashes from Java, that seems confusing to me, because it requires keeping track of escaping across both your Java and database layer.
As another general comment, if you used the Hibernate ORM layer to do the insert, or used a prepared statement, you wouldn't have to worry about this escaping problem.
I am trying to accomplish a simple licensing system in golang and have tried numerous ways to get it to work. Basically, I have input a couple of random licensing keys into my database and my golang program should check to see if the user-input key exists and if it does then add the user specified username and password into the database to login later.
This is the code that I have that hasn't been working:
"IF EXISTS (SELECT * FROM login WHERE LK = "+reglicenceEntry.Text()+") THEN
INSERT INTO `login` (`Username`, `Password`, `LK`) VALUES
('"+regusernameEntry.Text()+"', '"+regpasswordEntry.Text()+"', ''); "
This is the golang error:
Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS (SELECT * FROM login WHERE LK = '5qp515YHXEmSDzwqgoJh') THEN INSERT IN' at line 1
Thanks so much!
MySQL syntax doesn't support IF...THEN constructs except within stored routines and triggers and events. See https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-compound-statements.html
I suggest an alternative solution for your code:
INSERT INTO `login` (`Username`, `Password`, `LK`)
SELECT ?, ?, ''
FROM `login`
WHERE `LK` = ?
LIMIT 1
If your login table does not have the LK value, the SELECT above will return 0 rows, therefore it will not insert anything.
If your login table has the LK value, the SELECT above will return at least 1 row (and I limit it to 1), therefore it will insert a row. The row it inserts is comprised of your username and password, and a blank string for the LK.
I showed use of parameter placeholders. You should use parameters in SQL instead of concatenating variables into your query. This is good practice to avoid accidental SQL injection. See http://go-database-sql.org/prepared.html for examples.
The purpose of using parameters is to avoid SQL injection problems. See my answer to What is SQL injection? for an explanation of SQL injection.
Or my presentation SQL Injection Myths and Fallacies (or youtube video).
When using parameters, you do two steps.
The first step to prepare a query with placeholders (?) where you would otherwise concatenate variables into your SQL query.
The second step is to execute the prepared query, and this is the time you pass the variables to fill in the placeholders.
The point is to keep variables separate from your query, so if there's anything in the variable that could unintentionally change your SQL syntax (like imbalanced quotes), it is never combined with the SQL. After you do the prepare, the SQL has already been parsed by the MySQL server, and there's no way to change the syntax after that.
MySQL remembers which parts of the query need to be filled in, and when you pass variables during the execute step, MySQL fills in the missing parts of the query using your values — but this happens within the MySQL server, not in your application.
Thus the dynamic parts of the query — your variables — are kept separate from the SQL syntax and you avoid SQL injection problems.
For your task described in your question, it would look something like this (I have not tested this Go code, but it should put you on the right path).
stmt, err := tx.Prepare("INSERT INTO `login` (`Username`, `Password`, `LK`) SELECT ?, ?, '' FROM `login` WHERE `LK` = ? LIMIT 1")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
_, err = stmt.Exec(regusernameEntry.Text(), regpasswordEntry.Text(), reglicenceEntry.Text())
if err != nil {
log.Fatal(err)
}
The order of parameters is important. The variables you pass to Exec() must be in the same order that the ? placeholders appear in your prepared SQL statement. They are matched up, one for one, in the same order, by the MySQL server.
Do not put quotes around the placeholders in your prepared SQL statement. That will work as a literal string '?' in SQL. Use an unquoted ? character for a placeholder. When it gets combined by MySQL in the server, it will work as if you had put quotes around the value like a string — but with no risk of SQL injection even if that string value containing special characters.
Here's another site that gives more code examples: https://github.com/go-sql-driver/mysql/wiki/Examples
The Exec() function is for executing SQL that has no result set, like INSERT, UPDATE, DELETE. There are other functions in the Go SQL driver like Query() and QueryRow() that also accept parameter arguments. You'd use these if your SQL returns a result set.
I have the below perl extract:
$query = "INSERT INTO test (`MACADDR`)
VALUES ($MACADDR)";
print $query,"\n";
$db->do($query);
I got the below error when trying to insert to mysql and my mac address is 000E38F4E9CC:
DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '0E38F4E9CC)' at line 2 at insertmac.pl line 156.
Is perl mysql dbi able to insert mac address?
My other records is able to be inserted correctly except mac addresses.
Any idea?
Thanks.
As your passing in a string as a value you need to quote it
$query = "INSERT INTO test (`MACADDR`)
VALUES ('$MACADDR')";
Alternatively you can prepare it and use parameters
$query = "INSERT INTO test (`MACADDR`)
VALUES (?)";
my $q = $db->prepare($query);
$q->execute($MACADDR);
which is a better idea as you can reuse it for speed and it also avoid SQL injection attacks
I want to extract a text field from a database and insert it into some other database. So while extracting I used the REPLACE(message_text,'\'', '"') while selecting the test. I gave me an error. I changed that from my select statement and did it while initiating the global variable.
etl.globals['message_text'] = message_text;
still I'm getting an error at the insert statement
insert into lcs_al_user_likes(user_id,liked_user_id,post_content,loop_id) values('${etl.globals['posted_by']}','${etl.globals['liked_user_id']}','${etl.globals['message_text']}',?batchLoopCounter);
saying
*You have an error in your SQL syntaxcheck the manual that corresponds to your MySQL server version for the right syntax to use near 'message_text']}')' at line 1*
I think it is not getting the global variable. That I say because when i print its value using log it just gives me
${etl.globals['message_text']}
as output. So please help me out here.
<query connection-id="lcsDBConnection">
SELECT forum_topic_post_id AS forum_topic_post_id, posted_by AS posted_by,message_text as message_text FROM lcs_tbl_forum_topic_post WHERE like_count>0 LIMIT ?batchSize OFFSET ?queryCounter ;
<script connection-id="jexl">
etl.globals['forum_topic_post_id'] = forum_topic_post_id;
etl.globals['posted_by'] = posted_by;
etl.globals['message_text'] = message_text.replace('\'', '"');
</script>
It looks like the problem is in INSERT statement, you should use prepared statement
parameters escaping:
INSERT INTO lcs_al_user_likes(user_id,liked_user_id,post_content,loop_id) values(?{etl.globals['posted_by']},?{etl.globals['liked_user_id']},?{etl.globals['message_text']},?batchLoopCounter);
BTW As I understand, your original problem was quotes breaking the insert statement, so in this case with ?{parameter} syntax you don't need to use replace(...) function at all.
I'm new to Perl and was attempting to write a script on a RHEL box that will auto-configure a vanilla DB for new sites we create on our host. I already have the connect statement working and I'm able to connect and create a DB from the script (Used $dbh->do( qq(CREATE DATABASE $dbcreate) ); Is this the best way???), but I have a couple that I haven't been able to figure out how to make them work.
These are the mysql commands which I'm having issues with. Any suggestions? Thanks!
$dbh = DBI->connect("DBI:mysql:$db:$host", $user, $pass);
$dbh->do( qq(CREATE DATABASE $dbcreate) );
$dbh->do(qq(GRANT SELECT , INSERT , UPDATE , DELETE , CREATE , DROP , INDEX , ALTER , CREATE TEMPORARY TABLES , CREATE VIEW , SHOW VIEW , CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON `$dbcreate` . * TO 'moodle'#'%'`) );
$dbh->do( qq(FLUSH PRIVILEGES) );
$dbh->do( qq($dbcreate < MySQL_pristine.sql) );
$dbh->do( qq(USE $dbcreate) );
$dbh->do( qq(UPDATE md1_label SET content = REPLACE( content, "pristine", "$dbcreate")) );
$dbh->do( qq(UPDATE md1_label SET contents = REPLACE( contents, "pristine", "$dbcreate")) );
$dbh->do( qq(UPDATE md1_label SET questiontext = REPLACE( questiontext, "pristine", "$dbcreate")) );
DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GRANT SELECT , INSERT , UPDATE , DELETE , CREATE , DROP , INDEX ,�' at line 1 at create-auto-db.pl line 52.
DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'test3 < MySQL_pristine.sql' at line 1 at create-auto-db.pl line 54.
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 56.
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 57.
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 58.
The main issue you've encountered is interpolation of strings with containing an at-sign. If you have something like qq{Here is my email: test#hotmail.com} - this fails because it tries to put a list variable #hotmail, which doesn't exist. Either use a backslash to escape it (i.e., qq{Here is my email: test\#hotmail.com}), or if you don't need to interpolate any variables, use the non-interpolating quote q{...}.
Having said that, you need to be a little careful with some of these statements. You're putting variable values into these SQL statements, and that is a risk for SQL injection attacks. I'd use $dbh->quote($dbcreate) to get a string version, and $dbh->quote_identifier($dbcreate) to get an identifier version of the value of $dbcreate, and embed those values in. This is much safer, as it will avoid somebody doing a Bobby Tables on you and giving you a database name like: db'; DROP TABLE mysql.user; '; or similar. DBI provides both string and identifier quoting, so you can get the right kinds of quoting as needed. For example:
my $quoted_id_dbcreate = $dbh->quote_identifier($dbcreate);
$dbh->do( qq(USE $quoted_id_dbcreate) );
Placeholders are usually better, but some of these admin statements probably won't support them, so using proper quoting to inject the values is likely to be necessary.
Two things stand out to me.
$dbh->do(qq(GRANT SELECT , INSERT , (snip), EXECUTE ON '$dbcreate' . * TO 'moodle'#'%'`) );
...you've got a trailing backtick that you probably don't intend.
$dbcreate < MySQL_pristine.sql
...isn't quite what you want. I think you're trying to do is to read that file in Perl, and iterate over each contained SQL statement, calling "$dbh->do()" against it. If you're very lucky, you have one line per statement in that .sql file.