PHP/MYSQL Trouble Selecting by Primary Key [duplicate] - php

This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
So I have a primary key column called key. I'm trying to select the row with key = 1 via this code:
$query ="SELECT * FROM Bowlers WHERE key = '1'";
$result = mysql_query($query) or die(mysql_error());
For some reason, I'm getting this result:
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 'key = '1'' at line 1
The mysql statement works for using other keys, ie WHERE name = 'djs22'.
Any ideas?

key is a reserved word, try putting ticks around it:
$query ="SELECT * FROM `Bowlers` WHERE `key` = '1'";
$result = mysql_query($query) or die(mysql_error());
To see all the reserved words, go here and scroll down:
http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html

'key' is a reserved keyword, put backtick quotes around it:
"SELECT * FROM Bowlers WHERE `key` = '1'"

Without checking, it's likely that "key" is a reserved word in MySQL.
Try wrapping it in backticks
$query ="SELECT * FROM Bowlers WHERE `key` = '1'";

You should write the column name key in quotes
$query ="SELECT * FROM Bowlers WHERE `key` = '1'";
Otherwise it is a keyword

I run into that all the time. MySQL has a crap load of reserved words. And when you come across one, the mysql error function is not even nice enough to let you know what is wrong.
The only thing you can do is change the column name. I accidentally used "date, to and from" the other day. Was pulling my hair out when it dawned on me, DuHH!!! those are DB reserved.
You can wrap all kind of quotes around it, it does not matter when it references a column name. Reserved is reserved!
It is common practice to to do a couple of things.
1) When making tables: Split resource type with resource name using underscore. Example: xref_userMessages
This would mean it is a cross reference table for User messages.
2) Other examples of table names: msg_Messages | sys_Settings | cli_Logins
So any other table made related to messages would be called msg_??? , not only does this keep them grouped together in phpMyadmin but makes remembering the names easier too.
3) When Making columns: Never use a reserved. Thus causing key columns to always be 6 didgets. Example: admkey | usrkey | msgkey | clikey grpkey
Obviously Admin Key | User Key | Message Key | Client Key | Group Key
So this means "msg_Messages" keys are "msgkey" and the xref table would be xref_Messages and its keys are xref_msgkey. Following this logic you not only know what to name everything without even thinking about it, but you never run into any reserved words doing it.
4) Examples of Column names: dateInsert dateStart timeCreate admName admAddress admPhone admCell
Just like above there is a logic to it. Placing purpose/owner and noun/item together makes the name and again avoids reserved words.
Last Example:
Table: users_Admins users_Clients
Key: admkey usrkey
Table: msg_Messages
Columns: msgkey admkey usrkey msgRead msgMessage msgTitle
Just in this short example I avoided 2 reserved words. Key and Read
So in short, your problem is not reading a primary key. It is a problem with column names.
MySQL is seeing your code as having a syntax that has commands out of place. SELECT read ... or SELECT key ... it doesnt matter if you put quotes around it or not. MySQL is basically seeing ...
SELECT (SELECT,WHERE,FROM) FROM select,from,where
WHERE SELECT = WHERE & FROM = SELECT. hehehehehehehe
Putting a different kind of quote around this will not change the confusion level you just sent to MySQL.
Mixing my mistake and your mistake together looks like this...
SELECT key,from,to,date FROM my_table WHERE key='1';
// Same as...
SELECT SELECT,SELECT,SELECT,SELECT FROM my_table WHERE SELECT='1';
The first one you can't really tell by looking at it there is anything wrong with it. The second one it is obvious that it is not right and won't work. However, according to MySQL they are the SAME THING.
MySQL receives this syntax as so... SELECT? You told me to SELECT 5 times, never told me what to even select. You get the FROM right, but then you ended with a left hook telling to select something else, not only did you not tell me what to select again but you threw in an NULL='1'; what the heck is that all about?
This is why when you make these kinds of errors the error function doesn't even report what the heck happened. There were so many errors it can't throw you an error number so it just stops.
So this means your syntax is like this
SELECT * FROM Bowlers WHERE SELECT = '1';
Sometimes I get frustrated and say, "I wish MySQL was smarter than this!!!" But then I realize i would have to trade the key words in for a lesser valued database. Each one of those reserved words represents a word that is doing a whole lot more work on the database side for me. When I first started to learn programming I had to write my own text input field sub routines, so I appreciate all the neat things MySQL does for me.

Related

sql data does not show in php [duplicate]

One of my columns is called from. I can't change the name because I didn't make it.
Am I allowed to do something like SELECT from FROM TableName or is there a special syntax to avoid the SQL Server being confused?
Wrap the column name in brackets like so, from becomes [from].
select [from] from table;
It is also possible to use the following (useful when querying multiple tables):
select table.[from] from table;
If it had been in PostgreSQL, use double quotes around the name, like:
select "from" from "table";
Note: Internally PostgreSQL automatically converts all unquoted commands and parameters to lower case. That have the effect that commands and identifiers aren't case sensitive. sEleCt * from tAblE; is interpreted as select * from table;. However, parameters inside double quotes are used as is, and therefore ARE case sensitive: select * from "table"; and select * from "Table"; gets the result from two different tables.
These are the two ways to do it:
Use back quote as here:
SELECT `from` FROM TableName
You can mention with table name as:
SELECT TableName.from FROM TableName
While you are doing it - alias it as something else (or better yet, use a view or an SP and deprecate the old direct access method).
SELECT [from] AS TransferFrom -- Or something else more suitable
FROM TableName
Your question seems to be well answered here, but I just want to add one more comment to this subject.
Those designing the database should be well aware of the reserved keywords and avoid using them. If you discover someone using it, inform them about it (in a polite way). The keyword here is reserved word.
More information:
"Reserved keywords should not be used
as object names. Databases upgraded
from earlier versions of SQL Server
may contain identifiers that include
words not reserved in the earlier
version, but that are reserved words
for the current version of SQL Server.
You can refer to the object by using
delimited identifiers until the name
can be changed."
http://msdn.microsoft.com/en-us/library/ms176027.aspx
and
"If your database does contain names
that match reserved keywords, you must
use delimited identifiers when you
refer to those objects. For more
information, see Identifiers (DMX)."
http://msdn.microsoft.com/en-us/library/ms132178.aspx
In Apache Drill, use backquotes:
select `from` from table;
If you ARE using SQL Server, you can just simply wrap the square brackets around the column or table name.
select [select]
from [table]
I have also faced this issue.
And the solution for this is to put [Column_Name] like this in the query.
string query= "Select [Name],[Email] from Person";
So it will work perfectly well.
Hi I work on Teradata systems that is completely ANSI compliant. Use double quotes " " to name such columns.
E.g. type is a SQL reserved keyword, and when used within quotes, type is treated as a user specified name.
See below code example:
CREATE TABLE alpha1
AS
(
SEL
product1
type_of_product AS "type"
FROM beta1
) WITH DATA
PRIMARY INDEX (product1)
--type is a SQL reserved keyword
TYPE
--see? now to retrieve the column you would use:
SEL "type" FROM alpha1
I ran in the same issue when trying to update a column which name was a keyword. The solution above didn't help me. I solved it out by simply specifying the name of the table like this:
UPDATE `survey`
SET survey.values='yes,no'
WHERE (question='Did you agree?')
The following will work perfectly:
SELECT DISTINCT table.from AS a FROM table
Some solid answers—but the most-upvoted one is parochial, only dealing with SQL Server. In summary:
If you have source control, the best solution is to stick to the rules, and avoid using reserved words. This list has been around for ages, and covers most of the peculiarities. One tip is that reserved words are rarely plural—so you're usually safe using plural names. Exceptions are DIAGNOSTICS, SCHEMAS, OCTETS, OFFSETS, OPTIONS, VALUES, PARAMETERS, PRIVILEGES and also verb-like words that also appear plural: OVERLAPS, READS, RETURNS, TRANSFORMS.
Many of us don't have the luxury of changing the field names. There, you'll need to know the details of the RDBM you're accessing:
For SQL Server use [square_braces] around the name. This works in an ODBC connection too.
For MySQL use `back_ticks`.
Postgres, Oracle and several other RDBMs will apparently allow "double_quotes" to be used.
Dotting the offending word onto the table name may also work.
You can put your column name in bracket like:
Select [from] from < ur_tablename>
Or
Put in a temprary table then use as you like.
Example:
Declare #temp_table table(temp_from varchar(max))
Insert into #temp_table
Select * from your_tablename
Here I just assume that your_tablename contains only one column (i.e. from).
In MySQL, alternatively to using back quotes (`), you can use the UI to alter column names. Right click the table > Alter table > Edit the column name that contains sql keyword > Commit.
select [from] from <table>
As a note, the above does not work in MySQL
Judging from the answers here and my own experience. The only acceptable answer, if you're planning on being portable is don't use SQL keywords for table, column, or other names.
All these answers work in the various databases but apparently a lot don't support the ANSI solution.
Simple solution
Lets say the column name is from ; So the column name in query can be referred by table alias
Select * from user u where u.from="US"
In Oracle SQL Developer, pl/sql you can do this with double quotes but if you use double quotes you must type the column names in upper case. For example, SELECT "FROM" FROM MY_TABLE

Getting a Mysql Results without knowing a column name [duplicate]

This question already has answers here:
Get table column names in MySQL?
(19 answers)
Closed 9 years ago.
As I am still learning PHP and MySQL, I would like to know if it is possible to query a table without knowing it's name. Knowing the table I am querying and the column I would like to retrieve, I can write something like
$book_title=$row['book_title'];
Then I can use the resulting variable later in the script. In each case, each book category table will have a column of interest with a different name. I have several tables on which I am running queries. I am able to query any table by using a variable that always evaluates to the correct table name, because all the input from users corresponds to the tables in the database, so the $_POST super global will always carry a correct table name. The problem is for me to have a
$variable=$row['column'];
in cases where I do not know a column name before hand even though I know the table name.
My queries are simple, and look like
query="select * FROM $book_categories WHERE id=$id";
$row = mysqli_fetch_array ($result);
$variable=$row['?'];
The question mark say, I do not know what column to expect, as it's name could be anything from the tables in the database!
Since I have several tables, the query will zero on a table, but the column names in each table varies so I would like to be able to use one query that can give me an entry from such a column.
I hope my question is clear and that I am not asking for the impossible. If it's ambiguous, I care to elucidate (hope so).
I'm not sure what you mean, but it is possible to reference specifc columns by typing index (starting with 0) something like this: $row[0], $row[1] where 0 indicates the first column, and 1 indicates the second column from the returned recordset.
Example:
If you have a select-statement like this:
SELECT title, author FROM books
You could reference these two columns with $row[0], $row[1]
If you try to get the value of $row[2] you will get an unassigned value because there are only two columns (0 and 1) from the recordset.
If you have a select-statement like this:
SELECT * FROM book_categories
and the recordset returns three columns, then you could access these with $row[0], $row[1] and $row[2]. $row[3] does not exist because there are only three columns (0,1 and 2)
Since you are learning maybe we could take some time to explain why this is possible but many people (including myself) would say this is bad -- or at least dangerous
Why you can
Your SQL query is basically a text string you send to the DB server, which decode that string trying to interpret it as SQL in order to execute the query.
Since all you send to the DB server is text string, you could build that string however you want. Such as using string interpolation as you did:
select * FROM $book_categories WHERE id=$id
That way, you could replace any part of your query by the content of a variable. You could even go further:
$query FROM $book_categories WHERE id=$id
Where $query could by SELECT * or DELETE.
And, why not initializing all those variables from a form:
$book_categories = $_POST['book_categories'];
$id = $_POST['id'];
$query = $_POST['query'];
Great, no? Well, no...
Why you shouldn't
The problem here is "could you trust those variables to only contain acceptable values?". That is, what would append if $book_categories somehow resolve to one table you didn't want to (say myTableContainigSecretData)? And what if $id resolve to some specially crafted value like 1; DELETE * FROM myImportantTable;?
In these conditions, your query:
select * FROM $book_categories WHERE id=$id
Will become as received by the DB server:
select * FROM myTableContainigSecretData WHERE id=1; DELETE * FROM myImportantTable;
Probably not what you want.
What I've tried to demonstrate here is called SQL injection. This is a very common bug in web application.
How to prevent that?
The best way to prevent SQL injection is to use prepared statement to replace some placeholders in your query by values properly shielded against SQL injection. There was an example posted a few minutes ago as a response to an other question: https://stackoverflow.com/a/18035404/2363712
The "problem" regarding your initial question is that will replace values not table or columns identifiers.
If you really want to replace table/columns identifiers (or other non-value part of your query) by variables contents, you will have to check yourself the content of each of these variables in order to prevent SQL injection. This is quite feasible. But that's some work...

Alter table with PHP and MySQL, add a column with an '#' sign

I am trying to check if a table has a certain column in it, and if not add that column to it. My code appears to work fine as long as the input value does not have an # sign. I have tried surrounding
'$email'
with and without single quotes as an input string. Any help would be really appreciated.
$email = strtolower(mysql_real_escape_string($_SESSION['email']));
$result = mysql_query("SHOW COLUMNS FROM `selections` LIKE '$email'",$conn);
$exists = (mysql_num_rows($result))?TRUE:FALSE;
if ($exists == FALSE) {
$query2 = "ALTER TABLE selections ADD $email VARCHAR( 120 ) NOT NULL";
$add= mysql_query($query2,$conn);
var_dump($query2);
echo("this error". mysql_error());
}
$query2 was taken directly from phpmyadmin and seems to work there even with an # sign input
Thanks for your help!
Before anything else, please, please consider doing this in another way. You will be adding a field to a table for every email - what you probably do not know is that this increases the size of your table by increasing the size of the rows, and also limits you to a fixed number of fields (This link clearly highlights a total of 65535 bytes per row max. Every VARCHAR character, depending on charset, is between 3 and 8 bytes)
The real reason why your request is failing is because # is a special character in your SQL queries and phpmyadmin happens to be smart enough to escape it. # denotes a variable in the SQL dialect uses by MySQL. You can either backtick-escape it for MySQL, or you can quit using this in favour of a table structure like this:
selection:
* id
* your metadata here
emails:
* id
* email_address
selection_emails:
* id
* selection_id
* email_id
The third table is called an associative table. It allows you to keep normalizing your data.
You can surround the email with curly brackets {$email} to define it explicitly as a variable within a string, but you probably also need to escape odd characters in this variable before this.
When altering the table you should also surround this with back-ticks, to allow for odd characters.
The best approach would be to use parameterized queries, and drop the DEPRECATED mysql library. And also to not allow odd characters to be used in field names.
I would also question why you are adding email as a new column.

simple mysql select error limit [duplicate]

This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
This is the error message and my code. I just don't see the error.
Description:
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 'key='cbd1f3bb822e8617b624301774287490d3fcd97e' LIMIT 1' at line 1
Query:
SELECT *
FROM wp_wpsc_api_keys
WHERE name='MichelleAllen17'
AND key='cbd1f3bb822e8617b624301774287490d3fcd97e'
LIMIT 1
Any ideas of what can be the issue in my sql are welcome
KEY is a reserved keyword, it must be escaped with backtick.
SELECT *
FROM wp_wpsc_api_keys
WHERE name = 'MichelleAllen17' AND
`key` = 'cbd1f3bb822e8617b624301774287490d3fcd97e'
LIMIT 1
MySQL Reserved Keywords
put backtiks around the field names
...where `name`=... `key`
As an alternative to backticks, another "best practice" pattern is to QUALIFY all column names with the table_name, or a convenient table alias, e.g.
SELECT t.*
FROM wp_wpsc_api_keys t
WHERE t.name='MichelleAllen17'
AND t.key='cbd1f3bb822e8617b624301774287490d3fcd97e'
LIMIT 1
This prevents MySQL from seeing the column name "key" as a reserved word.
Let's be clear: the problem in your query isn't a lack of backticks... the problem is that MySQL is seeing a token in your query text (in this case "key") as a reserved word, rather than as the name of the column. The solution is to prevent MySQL from seeing that token as a keyword. Using backticks is one way to accomplish that, but they aren't required.
Using backticks is entirely valid, and can be done along with qualifying the column names. The backicks are required when the column name contains spaces or special characters. Here is the same query, with the table and column names enclosed in backticks:
SELECT t.*
FROM `wp_wpsc_api_keys` t
WHERE t.`name`='MichelleAllen17'
AND t.`key`='cbd1f3bb822e8617b624301774287490d3fcd97e'
LIMIT 1
I just happen to find it annoying to have to look at, or type, backticks that are unnecessary. It is MUCH MORE useful use of keystrokes (for me) to have the column names qualified ("t."), even if that isn't required, just because I am SO used to seeing column names qualified whenever there is more than one table in a query (which happens a LOT for a lot of really useful queries.)

I would like to use numbers 0-9 for mysql table names. How should I write sql queries using `` backticks to protect against sql query errors?

A user can post any topic title on my website, including pure numbers (eg. 12345). The topic title becomes the name of the table in mysql. I've encountered MYSQL errors in various places when testing out a number as a topic title, and have determined the problem is that I didn't use backtick marks to make sql queries.
How should I properly write all my queries to keep any possible title (table) from returning a mysql error? Code example below. What other potential table titles could cause problems?
<?php
for ($i=0; $i<4; $i++) {
// select by rand
$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `$random_slash[$i]` ");
$offset_row = mysql_fetch_object( $offset_result );
$offset = $offset_row->offset;
$result = mysql_query( " SELECT * FROM `$random_slash[$i]` LIMIT $offset, 1 " );
//$rs = #mysql_query($sql);
while ($row = mysql_fetch_array($result)) {?>
<div class="quadrant">
<h2 class="alignleft"><a href="/<?php echo $random_slash[$i]; ?>">
As a note - the tick marks seem to denote code
A user can post any topic title on my website, including pure numbers (eg. 12345). The topic title becomes the name of the table in mysql.
Noooooo! Don't do this.
The topic title should become a value, not the name of a table.
Use one table to store the topics, one row per topic. Use a second table to store the children of that topic. Use a foreign key to link the child to the parent topic.
Mark's answer already shows what the real issue is, and how to solve it. But since you stated your question as being about backticks, here is some information about them:
They should be used to escape table and column names
They are not required if your table and column names contain only [a-zA-Z_] (except for names that are already reserved words)
They allow you to name tables and columns with arbitrary strings, containing spaces and many special characters (not any), as you wanted to do, but this is not recommended (mainly for compatibility).

Categories