SQL injection on fixed value? - mysql

I'm aware that if you're inserting a variable, it is always good to use mysqli_real_escape_string. But, if I'm inserting a fixed value which is not a variable, do I need to use that function?
For example, like the syntax below. I insert a name which is a variable, and also a value '1' into the status column. Is it safe to do that to avoid SQL injection for the column status? since it is not a variable.
"INSERT INTO customer(name, status) VALUES ('".mysqli_real_escape_string($conn, $name) ."', '1')";

When using mysqli, it is safest to use prepared statements:
$stmt=$mysqli->prepare("INSERT INTO customer(name, status)
VALUES (?, '1')";
$stmt->bind_param("s", $name);
(See http://php.net/manual/en/mysqli.quickstart.prepared-statements.php for the more detailed and working code).
In this you can leave static values as is, nobody can replace those. You can also alter your table:
ALTER TABLE customer ALTER COLUMN status DEFAULT '1';
Then you do not even have to set it any longer.

There is no objection and need to escape the values on constant as SQL Injection will not be done on static things..

Related

insert query is not working in mysql

I really don't know what is happening insert query is not working for me.
$query_getgreenyear = "INSERT INTO `greenityear` `ConsolidateYear` VALUES ('".$sentdata."')";
in $sentdata the value is ('A','B') and the datatype for ConsolidateYear is varchar.I need this value to be inserted into the database.
but i am getting error
You have a SQL syntax error near 'ConsolidateYear VALUES ('('A','B')')' at line 1.
Please help me in this regard.
I am new to database activities.
You forgot to place a bracket() for your column name.
Try this:
$query_getgreenyear = "INSERT INTO `greenityear` (`ConsolidateYear`)
VALUES ('".$sentdata."')";
Please take a look at the MySQL Reference Manual.
You need to surround your column name with parantheses in your INSERT statement:
$query_getgreenyear = "INSERT INTO `greenityear` (`ConsolidateYear`) VALUES ('".$sentdata."')";
And I would highly recommend you to use prepared statements as provided by your MySQL-extension (at least if you're not using the deprectated mysql_connect). This protects you against SQL injections.
INSERT INTO `greenityear` (`ConsolidateYear`) VALUES (...)
But, you really should be using prepared statements and not constructing statements as you are.
the correct syntax is
INSERT INTO `tablename` (`columnname1`,`columnname2`) VALUES ('value1','value2')
so your example would be like this:
$query_getgreenyear = "INSERT INTO `greenityear` (`ConsolidateYear`) VALUES ('".$sentdata."')";

mysql prepared statements which statement i should use

Is there any major difference between the following prepared statements? Which one is more preferred, if so why?
1:
$stmt = $db->prepare("INSERT INTO users(userName) VALUES (:user)");
$user = "Steve";
$stmt->bindParam(':user', $user);
$stmt->execute();
2:
$stmt2 = $db->prepare('INSERT into users(userName) VALUES(:user)');
$stmt2->execute(array(':user'=>'Steve'));
bindParam takes a variable parameter as a reference. That means variable value MIGHT be modified, depending on what you did (like invoked a stored procedure that alters value of variables passed to it).
That's why you should be using bindValue instead, unless you expect MySQL to alter the value of your variable.
Only actual MAJOR difference is that you cannot specify the variable type if you use your second scenario. Every parameter is treated as a string, while when using bindParam / bindValue, you have the freedom to define whether the parameter is a string or integer.
So what you should use then? Well, neither is wrong. If you find it easier to use second approach while inserting a lot of string data, then there's nothing wrong with it.

Update MySQL without specifying column names

I want to update a mysql row, but I do not want to specify all the column names.
The table has 9 rows and I always want to update the last 7 rows in the right order.
These are the Fields
id
projectid
fangate
home
thanks
overview
winner
modules.wallPost
modules.overviewParticipant
Is there any way I can update the last few records without specifying their names?
With an INSERT statement this can be done pretty easily by doing this:
INSERT INTO `settings`
VALUES (NULL, ...field values...)
So I was hoping I could do something like this:
UPDATE `settings`
VALUES (NULL, ...field values...)
WHERE ...statement...
But unfortunately that doesn't work.
If the two first columns make up the primary key (or a unique index) you could use replace
So basically instead of writing
UPDATE settings
SET fangate = $fangate,
home = $home,
thanks = $thanks
overview = $overview,
winner = $winner,
modules.wallPost = $modules.wallPost,
modules.overviewParticipant = $modules.overviewParticipant
WHERE id = $id AND procjectId = $projectId
You will write
REPLACE INTO settings
VALUES ($id,
$projectId,
$fangate,
$home,
$thanks
$overview,
$winner,
$modules.wallPost,
$modules.overviewParticipant)
Of course this only works if the row already exist, otherwise it will be created. Also, it will cause a DELETE and an INSERT behind the scene, if that matters.
You can't. You always have to specify the column names, because UPDATE doesn't edit a whole row, it edits specified columns.
Here's a link with the UPDATE syntax:
http://dev.mysql.com/doc/refman/5.0/en/update.html
No, it works on the INSERT because even if you didn't specify the column name but you have supplied all values in the VALUE clause. Now, in UPDATE, you need to specify which column name will the value be associated.
UPDATE syntax requires the column names that will be modified.
Are you always updating the same table and columns?
In that case one way would be to define a stored procedure in your schema.
That way you could just do:
CALL update_settings(id, projectid, values_of_last_7 ..);
Although you would have to create the procedure, check the Mysql web pages for how to do this, eg:
http://docs.oracle.com/cd/E17952_01/refman-5.0-en/create-procedure.html
I'm afraid you can't afford not specifying the column names.
You can refer to the update documentation here.

SQL query fails to insert with same column count, works with fewer columns inserted

In the example here, NULL values are normally other variables I pass through. I tried to pass NULL to see if that was the problem as those are the only values that can be NULL, everything else is required.
mysql_query("INSERT INTO `imstillr_crm`.`customerinfo`
(`id`, `companyname`, `primarycontact`, `primaryemail`,
`prefphone`, `secondarycontact`, `secondaryemail`, `optionalphone`,
`department`, `website`)
VALUES
(NULL, '".$company."', '".$primarycontact."', '".$primaryemail."',
'".$prefphone."', 'NULL', 'NULL', 'NULL,
'".$department."', '".$website."')");
I just tried this with fewer variables and it worked. I'm kinda confused. I even inserted a record and copied the SQL string and added my variables.
I think you've made a mistake here:
'NULL, '".$department.
Presumably you intended
'NULL', ".$department."
BUT: this looks as though you are attempting to insert the literal text "NULL" into your database which I assume is not what you intend. NULL is a keyword so you can just use the bare word NULL wherever you are inserting a null value (so no quotes required around it).
There's more though, at the risk of distracting you from your current issue, you really should not execute SQL statements by composing a string as you are doing. This is how SQL injection attacks succeed. A better way is to use PDO with prepared statements. Here's a quick description of how to use it:
http://www.php.net/manual/en/pdo.prepared-statements.php
The main advantages are:
You remove the explicit dependency on Mysql created by the mysql_* functions
You can avoid SQL injection attacks.
Your code should be easier to read without the complex string composition
Just for completeness, here's how your code would look with PDO
$stmt = $dbh->prepare("INSERT INTO imstillr_crm.customerinfo (id, companyname, primarycontact, primaryemail, prefphone, secondarycontact, secondaryemail, optionalphone, department, website) VALUES (:id, :companyname, :primarycontact, :primaryemail, :prefphone, :secondarycontact, :secondaryemail, :optionalphone, :department, :website)");
$stmt->bindParam(":id", NULL);
$stmt->bindParam(":companyname", $company);
$stmt->bindParam(":primarycontact", $primarycontact);
...
$stmt->execute();
Notice how you don't need to put quotes around the values. They might contain various characters so as quotes, semi colons etc. and these won't cause any problems in your database (they may cause problems elsewhere in your app but that's another discussion).
I don't think you can put NULL in quotes. I think you need to remove the quotes around NULL otherwise MySQL (I'm guessing MySQL) will treat them as strings.
A ' is missing after the last NULL
Corrected code:
mysql_query("INSERT INTO `imstillr_crm`.`customerinfo` (`id`, `companyname`, `primarycontact`, `primaryemail`, `prefphone`, `secondarycontact`, `secondaryemail`, `optionalphone`, `department`, `website`) VALUES (NULL, '".$company."', '".$primarycontact."', '".$primaryemail."', '".$prefphone."', 'NULL', 'NULL', 'NULL', '".$department."', '".$website."')");
You have mixed up the ' and ,:
'NULL, '".$department."'
Should be:
'NULL', '".$department."'
Right before $department you have 'NULL, '" you probably want to move the quote in before the comma.

Why does my INSERT sometimes fail with "no such field"?

I've been using the following snippet in developements for years. Now all of a sudden I get a DB Error: no such field warning
$process = "process";
$create = $connection->query
(
"INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));
but it's fine if I use numerics
$process = "12345";
$create = $connection->query
(
"INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));
or write the value directly into the expression
$create = $connection->query
(
"INSERT INTO summery (process) VALUES('process')"
);
if (DB::isError($create)) die($create->getMessage($create));
I'm really confused ... any suggestions?
It's always better to use prepared queries and parameter placeholders. Like this in Perl DBI:
my $process=1234;
my $ins_process = $dbh->prepare("INSERT INTO summary (process) values(?)");
$ins_process->execute($process);
For best performance, prepare all your often-used queries right after opening the database connection. Many database engines will store them on the server during the session, much like small temporary stored procedures.
Its also very good for security. Writing the value into an insert string yourself means that you must write the correct escape code at each SQL statement. Using a prepare and execute style means that only one place (execute) needs to know about escaping, if escaping is even necessary.
Ditto what Zan Lynx said about placeholders. But you may still be wondering why your code failed.
It appears that you forgot a crucial detail from the previous code that worked for you for years: quotes.
This (tested) code works fine:
my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
VALUES (3,'$thing')");
$sth->execute;
But this next code (lacking the quotation marks in the VALUES field just as your first example does) produces the error you report because VALUES (3,$thing) resolves to VALUES (3,abcde) causing your SQL server to look for a field called abcde and there is no field by that name.
my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
VALUES (3,$thing)");
$sth->execute;
All of this assumes that your first example is not a direct quote of code that failed as you describe and therefore not what you intended. It resolves to:
"INSERT INTO summery (process) VALUES(process)"
which, as mentioned above causes your SQL server to read the item in the VALUES set as another field name. As given, this actually runs on MySQL without complaint and will fill the field called 'process' with NULL because that's what the field called 'process' contained when MySQL looked there for a value as it created the new record.
I do use this style for quick throw-away hacks involving known, secure data (e.g. a value supplied within the program itself). But for anything involving data that comes from outside the program or that might possibly contain other than [0-9a-zA-Z] it will save you grief to use placeholders.