Syntax Error MYSQL 1064 - mysql

I've had this error attempting to create a table that I just can't figure out. I'll try to explain it to the best of my abilities.
In the mysql command line, I'm entering
CREATE TABLE index(references INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(600), description VARCHAR(2500));
It repetitively gives me the 1064 error telling me something is wrong in the syntax that is near 'index(references INT NOT N... name VARCHAR(5600), des'.
I've tried renaming the table to random letters thinking it was possibly the name though no, any ideas anybody? I really would appreciate any help, thank you!
EDIT: My version does support VARCHAR's over 255 also.
EDIT 2: Solved, renamed a couple data type names and the table name ^.^, thanks for everybody's help!

I know this gets through. Use back-ticks. And a typo on varchar.
CREATE TABLE `index`
( `references` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(600),
`description` VARCHAR(2500)
);
Take a look at Mysql Reserved Words and Keywords
Special care must always be used with the names with an (R) in that link. They need back-ticks. Better yet, choose another word/name.
Edit: To answer one of your comment questions below.
create table `table2`
(
`id` int auto_increment primary key,
`colB` decimal(12,2) not null
);
insert table2 (colB) values (3.14),(100);
select * from table2;
+----+--------+
| id | colB |
+----+--------+
| 1 | 3.14 |
| 2 | 100.00 |
+----+--------+

Related

Insert auto-incremental id on Kettle/Spoon

I have a single column of "names" on a text file.
And I want to add this column to my database's table "names" that already exists and has a lot of names.
That's looked very simple, but I don't know how to add the auto-incremental ID
I have something like this:
names
John
Lars
Peter
I wanted something like this.
id | names
.........
68 | John
69 | Lars
70 | Peter
This is how I create my table:
CREATE TABLE IF NOT EXISTS `names` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '',
`name` VARCHAR(45) NOT NULL COMMENT '',
PRIMARY KEY (`id`) COMMENT '')
ENGINE = InnoDB;
There are two details to take in consideration:
1 - If you do not want two rows with the same name in the database.
To accomplish that you must set only the name field in the lookup part of the insert/update task.
2 - If you can have two rows with the same name.
Do not put anything in the lookup part of the insert/update task.
Kettle will not include the ID colummn in insert on both cases. Mysql will define the next ID automatically as the ID field is marked as auto_icrement.
UPDATE
Please, take a look in the target table field. You have defined the "domain" table instead of "names".

What's the best way to normalise this database?

First of all thank you for reading my problem and I hope that you can help me.
So I'm creating an API to use later on in my Android App, but I'm having doubts about the correct way that I need to create the database that I'm working with. The way I've got the database setup now is like this:
But this does not look good and doesn't help with what I want to do in my API. I want my users to able to input symptoms and then my API outputs illnesses based on the input of the users.
So, I think I need to change my database design but what should it look like? I've been struggling over this for the past day and I can't seem to find the correct answer.
Again, thanks for reading!
There are two ways you can improve the structure of your database. The first one is simpler but the second one is more strict and completely normalized:
Way 1
Create an illness table:
CREATE TABLE illness(
id INTEGER NOT NULL AUTO_INCREMENT,
illnessName VARCHAR(255) UNIQUE NOT NULL,
PRIMARY KEY(illnessId)
);
Then create a table that uses each ilness' unique id to match it with its symptoms in a 1:n relationship.
CREATE TABLE illness_symptom(
illnessId INTEGER NOT NULL,
symptom VARCHAR(255),
FOREIGN KEY (illnessId) REFERENCES illness(id)ON UPDATE CASCADE ON DELETE CASCADE,
PRIMARY KEY(illnessId, symptom)
);
The dual primary key ensures that no symptom is included twice for the same illness.
The fact that the symptom is a string makes it less strict than the following method which is the best:
WAY 2
The illness table remains the same as in way 1:
CREATE TABLE illness(
id INTEGER NOT NULL AUTO_INCREMENT,
illnessName VARCHAR(255) UNIQUE NOT NULL,
PRIMARY KEY(illnessId)
);
Create a whole separate table for storing every possible symptom:
CREATE TABLE symptom(
id INTEGER NOT NULL AUTO_INCREMENT,
symptomName VARCHAR(255) UNIQUE NOT NULL,
PRIMARY KEY(id)
);
The create a third table that matches the id of the illness with the id of the symptom:
CREATE TABLE illness_symptom(
illnessId INTEGER NOT NULL,
symptomId INTEGER NOT NULL,
PRIMARY KEY(illnessId, symptomId),
FOREIGN KEY(illnessId) REFERENCES illness(id),
FOREIGN KEY(symptomId) REFERENCES symptom(id)
);
Again the dual primary key ensures that an illness does not include the same symptom more than once
EDIT
After creating the tables you can join them to get match each illness with its symptoms like this:
SELECT i.id, i.illnessName AS illnessName, s.symptomName AS symptomName
FROM (illness AS i JOIN illness_symptom AS is ON i.id=is.illnessId) JOIN symptom AS s ON is.symptomId=s.id
GROUP BY i.id;
An example output would something like this:
1 | Bronchitis | stuffiness
1 | Bronchitis | fatigue
1 | Bronchitis | thightness in the chest
2 | Whiplash | headache
2 | Whiplash | dizzyness
2 | Whiplash | concentration problems
You can read more about inner join here
Actually you can have three tables:
1. Illness Table
2. Symptom Table
3. IllnessSymptom Table
1.Illness Table will have IllnessID,Illname
2.Symptom table will have SymptomID,SymptomName
3.IllnessSymptom Table will have IllnessSymptomID,IllnessID,Symptom which will relate Illness and Symptom
You can make your API fetch data by joining these table
So the query would be like
SELECT I.IllnessName IS
INNER JOIN Illness I ON IS.IllnessID=I.IllnessID
INNER JOIN Symptom S OM IS.SymptonID=S.SymptonID
WHERE S.SymptomName=#YourInputIllness
Hope this answers your query! :)

getting the total consumption

if i have the following tables:
create table rar (
rar_id int(11) not null auto_increment primary key,
rar_name varchar (20));
create table data_link(
id int(11) not null auto_increment primary key,
rar_id int(11) not null,
foreign key(rar_id) references rar(rar_id));
create table consumption (
id int(11) not null,
foreign key(id) references data_link(id),
consumption int(11) not null,
total_consumption int(11) not null,
date_time datetime not null);
i want the total consumption to be all the consumption field values added up. Is there a way to accomplish this through triggers? or do i need to each time read all the values + the latest value, sum them up and then update the table? is there a better way to do this?
--------------------------------------------------
id | consumption | total_consumption | date_time |
==================================================|
1 | 5 | 5 | 09/09/2013 |
2 | 5 | 10 | 10/09/2013 |
3 | 7 | 17 | 11/09/2013 |
4 | 3 | 20 | 11/09/2013 |
--------------------------------------------------
just wondering if there is a cleaner faster way of getting the total each time a new entry is added?
Or perhaps this is bad design? Would it better to have something like:
SELECT SUM(consumption) FROM consumption WHERE date BETWEEN '2013-09-09' AND '2013-09-11' in order to get this type of information... would doing this be the best option? The only problem i see with this is that the same command would be re-run multiple times - where each time the data would not be stored as it would be retrieved by request....it could be inefficient when you are re-generating the same report several times over for viewing purposes.... rather if the total is already calculated all you have to do is read the data, rather than computing it again and again... thoughts?
any help would be appreciated...
If you've got an index on total_consumption it won't noticeably slow the query down to have a nested select of MAX(total_consumption) as part of the insert as the max value will be stored already.
eg.
INSERT INTO `consumption` (consumption, total_consumption)
VALUES (8,
consumption + (SELECT MAX(total_consumption) FROM consumption)
);
I'm not sure how you're using the id column but you can easily add criteria to the nested select to control this.
If you do need to put a WHERE on the nested select, make sure you have an index across the fields you use and then the total_consumption column. For example, if you make it ... WHERE id = x, you'll need an index on (id, total_consumption) for it to work efficiently.
if You MUST have trigger - it shoud be like that:
DELIMITER $$
CREATE
TRIGGER `chg_consumption` BEFORE INSERT ON `consumption`
FOR EACH ROW BEGIN
SET NEW.total_consumption=(SELECT
MAX(total_consumption)+new.consumption
FROM consumption);
END;
$$
DELIMITER ;
p.s. and make total_consumption int(11) not null, nullable or default 0
EDIT:
improve from SUM(total_consumption) for MAX(total_consumption) as #calcinai suggestion

Mysql VARCHAR to CHAR conversion behavior question

I'm looking at this Mysql question link:
And I can't repeat the behavior described in the answer to that question.
I tried creating tables with CHAR and VARCHAR column of various lengths and it doesn't matter what length - SHOW CREATE TABLE always return the data type that I've originally defined.
So - no CHAR->VARCHAR switching is going on.
Is answer to the question below only partially correct (I'm talking only about items 1 and 2)?
Q:
When you create a table, and then run SHOW CREATE TABLE on it, you occasionally get different results than what you typed in. What does MySQL modify in your newly created tables?
A (supposedly):
VARCHARs with length less than 4 become CHARs
CHARs with length more than 3 become VARCHARs.
NOT NULL gets added to the columns declared as PRIMARY KEYs
Default values such as NULL are specified for each column
There is a page in the MySQL's manual that answers some of your questions : 12.1.14.2. Silent Column Specification Changes.
Quoting some portions that correspond to items you posted in your question :
For item 3 :
Columns that are part of a PRIMARY
KEY are made NOT NULL even if not
declared that way.
About the size of varchar columns (not exactly one of your items, though) :
If strict SQL mode is not enabled, a
VARCHAR column with a length
specification greater than 65535 is
converted to TEXT, and a VARBINARY
column with a length specification
greater than 65535 is converted to
BLOB. Otherwise, an error occurs in
either of these cases.
And that page ends with the following sentence :
To see whether MySQL used a data type
other than the one you specified,
issue a DESCRIBE or SHOW CREATE
TABLE statement after creating or
altering the table.
So I'm guessing you might expect some additional differences, that are not listed.
Doing a quick test, here's a create table statement :
create table test_2 (
id int primary key,
blah_vc varchar(2),
blah_c char(5)
) engine=InnoDb;
And the table that's created gives :
mysql> desc test_2;
+---------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| blah_vc | varchar(2) | YES | | NULL | |
| blah_c | char(5) | YES | | NULL | |
+---------+------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> show create table test_2;
+--------+--------------------------------------------+
| Table | Create Table |
+--------+--------------------------------------------+
| test_2 | CREATE TABLE `test_2` (
`id` int(11) NOT NULL,
`blah_vc` varchar(2) DEFAULT NULL,
`blah_c` char(5) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+--------------------------------------------+
1 row in set (0.00 sec)
So :
no : varchar has not been transformed to char
no : char has not been transformed to varchar
yes : not null has been added to primary key
well, that one is funny : describe says it hasn't,
but show create table indicates it has...
Anyway : it makes sense, for a primary key column, to not be nullable.
yes : null is specified as default for columns that can be null.
That question is pretty old, written back in the days of MySQL 4.
As of MySQL 5.0, 1 & 2 from that list are no longer true.

alter table add ... before `code`?

ALTER TABLE tada_prod.action_6_weekly ADD COLUMN id INT NULL AUTO_INCREMENT UNIQUE AFTER member_id;
works,
so i thought, to add the column as the first column i could do
ALTER TABLE `tada_prod`.`action_6_weekly` ADD COLUMN `id` INT NULL AUTO_INCREMENT UNIQUE BEFORE `code`;
but i get a syntax error,
what is the correct syntax?
ALTER TABLE `tada_prod`.`action_6_weekly`
ADD COLUMN `id` INT NULL AUTO_INCREMENT UNIQUE FIRST;
You can add column only after particular field or at first not before.
The mysql query for add column after particular filed is:ALTER TABLE table_name ADD COLUMN column_name VARCHAR(30) AFTER column_name
Actually,
alter table table_name ADD column_name VARCHAR(12) NOT NULL BEFORE specific_column_name;
This command is not allowed in mySQL syntax. If you use it I think you get
" 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 'before specific_column_name' at line 1 " message.
You can try:
ALTER TABLE table_name ADD column_name VARCHAR(12) NOT NULL FIRST;
Extending #php answer, I think the rationale behind not including BEFORE is because all the effects of BEFORE can be easily achieved using AFTER and FIRST
For Ex:
Let's say, initially you have a relational schema like
+----------------------+
| name | age | address |
+----------------------+
and then for some reason you're compelled to add a new column dob(date of birth) just before age, but since BEFORE is not allowed, what you can do instead is insert dob just after the name using AFTER and very well achieve the same effect.
+----------------------------+
| name | dob | age | address |
+----------------------------+
But what if you wanted to insert a new column `id` before `name`?
Since there is no column before name we cannot use AFTER to place the id column. In-order to resolve this, the language designers introduced FIRST which makes the desired id column as the first column of the table.
+---------------------------------+
| id | name | dob | age | address |
+---------------------------------+
Although I personally think AFTER and BEFORE would've made a more intuitive pair.