MySQL not querying primary key - mysql

I'm confused with MySQL. I'm querying a table with a primary key field called index.
SELECT * FROM content WHERE index = 7
Pretty simple right? I keep getting a syntax error though, around index = 7, error number 1064 (can't paste the error as it's on an iPhone simulator).
The field index contains a 7. It is the PRIMARY_KEY, and of type int(6)
The database works fine querying other fields and so on.
Are there settings I need to ensure are in place before I can query this field?
Much appreciated.

SELECT * FROM content WHERE `index` = 7
index is a reserved word in MySQL. You have to escape it with backticks. See here

Another suitable workaround (for a column identifier which is a reserved word) is to qualify the column with the table name or a table alias. My preference is to always use a table alias. In this example, we give the table content an alias of c, which we can then reference in the query:
SELECT c.* FROM content c WHERE c.index = 7
In this example, backticks are not required around the column name, because when it is qualified with a table alias, MySQL sees it as an identifier; a reserved word can't be qualified with a table name.
Using a table alias is a pattern we use in more complex statements, which reference multiple tables and/or reference the same table multiple times. Nothing prevents us from using the same pattern with simple statements.
And the backticks around identifiers is always allowed, even if they are required:
SELECT `c`.* FROM `content` `c` WHERE `c`.`index` = 7

Index is a reserved word, use
Select * from content
where `index` = 7

Related

Is this proper way to create indexes?

How does INDEX work with MYSQL?
Suppose I got 2 tables like this
//customerTable
id auto_increment,
username char(30),
password char(40),
phone int(10)
//profileTable
id auto_increment,
username char(30),
description text
And I created an INDEX on username on both tables, like this
create index username on `customerTable` ( username, password )
create index username on `profileTable` ( username )
Then I run these queries:
select * from `customerTable` where username='abc' limit 1
select * from `customerTable` where username='abc' and password='xyzzzzz' limit 1
select customerTable.*, profileTable.* from
customerTable, profileTable where
customerTable.username='abc'
and customerTable.password='xyzzzzzzz'
and customerTable.username = profileTable.username
limit 1
Which indexes will these 3 queries use? Because name of both indexes is same...
Index names must be unique within the same table. That is, you can't have two indexes in the same table and name both indexes username.
You can reuse an index name on a different table, like you have shown. Index names don't have to be unique over multiple tables. In this way, they are like column names. You can use the same column name in more than one table.
Some people like to define a naming convention for their index names, but it doesn't really affect anything as far as the database is concerned.
I'm especially puzzled when I see developers who think they have to use "idx_" as a prefix for every index name. It's not necessary, it's just four extra characters you have to type.
The SQL query optimizer knows which index belongs to each table, even if they have the same name. It will not get confused.
You might like my presentation How to Design Indexes, Really, or the video of me presenting it: https://www.youtube.com/watch?v=ELR7-RdU9XU
P.S.: I have a couple of comments that are not directly related to your question, but I have to caution you:
Please don't store passwords in plain text. If a hacker gains access to your database, you'll be sorry. Read You're Probably Storing Passwords Incorrectly.
You're using old-fashioned syntax for your joins. Read Why isn't SQL ANSI-92 standard better adopted over ANSI-89?

SQL using "in" for looking up substrings

So, we know this one works when I want to select all ID's that are present in the inner sql statement
Select *
FROM TableA
WHERE Column1 IN (SELECT column2 FROM tableB WHERE = condition)
What kind of syntax do I need to do if Column1 is a long string and I need to check if a certain substring exists.
Ex Column1 = "text text text text 12345" where 12345 is an ID that is present in the list of ID's given by the inner sql statement
Basically I'm trying to detect if an ID is present in one of strings from another table based on my list of ID's from another table.
Should I do this in SQL or let a serverside code do it?
This is usually done using the LIKE operator:
SELECT ... FROM ... WHERE Column1 LIKE "%12345%";
However this is extremely slow, since it is based on substring matching. To improve performance you have to create a search index table storing single words. Such index typically is maintained by trigger definitions: whenever an entry is changed the trigger also changes the set of words extracted into the search index table. Searching in such an index table is obviously fast and can be combined with the original table by means of a JOIN based on the n:1 relationship between words in the index to the original entries in your table.
Instead of using fieldname like '%needle%' search, which is extremely slow because it cannot utilise indexes, create a fulltext index on the given column and use fulltext search to find the matching substring.
Below code excerpt is quoted from the MySQL documentation:
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
) ENGINE=InnoDB;
SELECT * FROM articles
WHERE MATCH (title,body)
AGAINST ('database' IN NATURAL LANGUAGE MODE);
The catch with syntax is that the list of words being looked for ('database' in the above code example) must be a string literal, it cannot be a subquery. You need to assemble the list of keywords in the application that calls the sql statement.

Creating Unique Compound Index where one field can be null in Mysql

I created Unique Compound Index:
Alter Table TableX Add Unique Index `UniqueRecord` (A,B,C,D)
The issue is that sometimes C can be NULL.
I noticed that
`Insert IGNORE`
Was still in some cases adding duplicate records and this turned out to be when those incoming records had C as NULL.
I tested the hypothesis that this was an issue by doing:
Select concat(A,B,C,D) as Index from TableA where C is NULL
And Index in each of those cases was in fact NULL. Once I remove the null field from the select:
Select concat(A,B,D) as Index from TableA where C is NULL
I get the expected string values vs nulls.
So the question is, other than doing an update like set C='' where C is NULL is there some way to set up the Index so that it works? I am loathe to simply make the Index A,B,D as that might introduce unwanted dupes when C in fact is not NULL.
Update:
I did try using IfNull in the Index creation but Mysql did not like that:
Alter Table TableA Add Unique Index UniqueLocator (A,B,IfNull(C,''),D
Mysql said:
[Err] 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 'C,''),D)' at line 1
Yes MySQL allows NULLs in unique indexes, which is the right thing to do. But you can define column C as NOT NULL if you don't like that.
MySQL -- but not all databases -- allow duplicate NULL values in unique indexes. I believe the ANSI standard is rather ambiguous on this point (or perhaps even contradictory). You basically have two choices.
The first is to define a default value for the column. This may not be appealing in terms of code, but it will at least generate an error on duplicate insert. For instance, if "C" is a foreign key reference to an auto-incremented id, then you might use -1 or 0 as the default value. If it is a date, you might use the zero date.
The other solution is a trigger, where you manually check for the duplicate values before doing an insert (or update).

adding FULLTEXT index : didn't make much difference , is it going to index older data?

i have a query which is using a like condition and it's killing my server
(this query is what i get frequently in the slow-query-log )
btw my table has about 120k rows - pleas ignor the syntax errors
select * from `images` where `category` like `%,3,%` and ( `tags` like '%,tag1,%' or `tags` like '%,tag2,%' or `tags` like '%,tag3,%' or `tags` like '%,tag4,%')
i don't want to change the query and database design fro now , so i've decided to switch to myisam and use fulltext index for tags column .
afterward server load hasn't change that much , mysql still using up to 90% of cpu (1 out of 8 of curse) from time to time .
so i was wondring , this fulltext indexing ... is it going to index the older data ( before adding this index ) ? cuz it happend very fast and my table is kinda big .
or it's only going to work on the newly stored data ?
Existing data was indexed, but as advised by Pyrce, a query with LIKE %[token]% is unable to leverage a fulltext index.
Rewrite your condition like this, this strictly equivalent to your inital query (ignoring stopwords and the likes):
WHERE MATCH(tags) AGAINST ('tag1 tag2 tag3 tag4' IN BOOLEAN MODE)
However you should rather focus on normalizing your structure. Storing non-scalar values (such as coma-separated values) in a field violates the very first normal form.
Create a new image_tag table and establish a 1-N relationship with images. A regular index will allow instant querying.
CREATE TABLE image_tags (
image_id INT,
tag VARCHAR(50),
PRIMARY KEY (image_id, tag),
FOREIGN KEY (image_id) REFERENCES images(id), -- replace with "images" table's actual primary key
KEY(tag, image_id) -- this index may be superfluous, check EXPLAIN
);
SELECT images.*
FROM images
JOIN image_tags ON image_id = images.id
WHERE tag IN ('tag1', 'tag2', 'tag3', 'tag4');
Repeat with images.category.
Full-text indexing usually only helps with prefix matching on tokens. In other words, all non-alphanumeric plus underscore separated words (anything other than A-Z, 0-9, or _ separates a word -- see here) within each row for the tags column will be indexed for prefix matches. You then have to use MATCH (tags) AGAINST ('tag1') to match the full text index search. You can repeat these matches for each tag to get your full query. Doing an Explain query will tell you if the query builder is using your index once you get the match queries fully configured.
Unfortunately MySQL is rather limited in how you can alter the full text indexing/searching -- so you're mostly stuck with it's default search methods (there's a couple search modes for fulltext -- see docs).

MySQL SELECT Statement against an Index

I have a table that is indexed on the first 2 columns. Column A is called "directory" and Column B is called "name".
Is there short syntax for my select statement that I can use to return the proper row?
Example:
Can I
SELECT * FROM table WHERE indexname = '/dir/sub-dir/page.html'
or do I have to
SELECT * FROM table WHERE directory = '/dir/sub-dir/' AND name = 'page.html'
If I can use the first example, what does the WHERE clause look like?
Thanks.
If you have an index defined against both columns, the second usage is the proper one. In SQL, you can only define predicates against columns in tables, views, or table valued user-defined functions (which I don't think MySQL has yet). You can't select off an index, but the optimizer will know to use the appropriate index when you include both columns.