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".
Related
I need a searchable database with messages, which I can attach tags to, and see whether they have been used, when and where.
For example, I got the following message "Hi! I live in Stockholm and are looking for a handyman. I saw in your profile that you own a toolbox and since I don't own any tools myself, except for a screwdriver, I was hoping that hiring you would be the best since yo can bring your own tools! Please contact me ASAP!"
To this message, I want to attach the tags "Stockholm, handyman, toolbox, screwdriver and tools".
When searching the database, I wish to be able to find all messages containing the tags "Stockholm" and "Toolbox".
If I then decide to use this message above, and use it, I want to be able to set that it was used 2018-02-11 11.52 using the name "John Doe" at the site "findahandyman.site".
Now, this is all fictional, I will use completely different messages with other tags, places etc. But the scenario is real. However, I am not sure what way to do this best would be.
I am thinking like this:
tbl-tags
----------
|id | tag |
----------
tbl-messages
--------------
| id | message |
--------------
tbl-used
-------------------------
| id | date | name | site |
-------------------------
And then build a view where I can search the messages, registered with the tags #1 #2 #3 etc.
Am I thinking right? If I am, how can I relate them all and how to build the view. If I am not, how should I think? And also, how to relate them all and build the view according to your suggestion(s)?
In my opinion you would need to do this:
1.) make the parent tables like this:
create table tbl_tags
(
tagName VARCHAR(50) NOT NULL,
dateAdded datetime NULL,
primary key(tagName)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
create the tbl_message table using an id as a primary key (tagName is here primary because this way tag names will not duplicate) like this:
create table tbl_messages
(
message_ID INT(11) NOT NULL AUTO_INCREMENT,
message text NOT NULL,
dateAdded NULL,
primary key(message_ID)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
For the tbl_used I would make it a mapping table with three columns. One column would be the message_ID (a foreign key from the table tbl_messages) and the other the date and time it was used, I would also add an id as primary here to avoid getting an error if multiple users try to use the same message at the same time.
create table tbl_used
(
used_ID INT(11) NOT NULL AUTO_INCREMENT,
message_ID INT(11) NOT NULL,
timeOfUse dateTime NOT NULL,
PRIMARY KEY (`used_ID`),
FOREIGN KEY (`message_ID`) REFERENCES `tbl_messages` (`message_ID`) ON UPDATE CASCADE
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
2.) create another mapping table to relate the messages and tags tables to each other:
create table tbl_messages_x_tbl_tags
(
message_ID INT(11) NOT NULL,
tagName VARCHAR(50) NOT NULL,
PRIMARY KEY (`message_ID`, `tagName`),
FOREIGN KEY (`message_ID`) REFERENCES `tbl_messages` (`message_ID`) ON UPDATE CASCADE,
FOREIGN KEY (`tagName`) REFERENCES `tbl_tags` (`tagName`) ON UPDATE CASCADE
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
You will notice that you will be unable to populate the foreign key columns in the mapping tables with arbitrary content. You can only insert valid values from their respective parent tables. That means your mapping table data is consistent.
To fill the tables, you first need to fill the parent tables (tbl_messages, tbl_tags), then you can populate the mapping tables (tbl_messages_x_tbl_tags, tbl_used).
On insertion of a new message you would simply check for new tags and insert new tags into the table tbl_tags if they are not already there. Then add the message into tbl_messages and populate the mapping table tbl_messages_x_tbl_tags with (message_ID, tagName) rows.
After that, on each use of the message you can simply write to the database:
mysqli_query($connection, "INSERT INTO tbl_used (message_ID,timeOfUse) VALUES($msgID, NOW())");
tbl-tags
----------
|id | tag |
----------
tbl-message-tags
----------------------
| id | tag_id | msg_id |
----------------------
tbl-messages
--------------
| id | message |
--------------
tbl-used
-------------------------
| id | date | name | site |
-------------------------
Creating tables (if you want, you can add constraints):
create table tbl_tags(id mediumint not null auto_increment, tag varchar(255) not null, primary key(id));
create table tbl_messages(id mediumint not null auto_increment, message text not null, primary key(id));
create table tmt(tag_id mediumint not null, msg_id mediumint not null, primary key(tag_id, msg_id));
Insert some test data:
insert into tbl_tags(tag) values ('tag0'), ('tag1');
insert into tbl_messages(message) values ('msg1'), ('msg2'), ('msg3'), ('msg4'), ('msg5');
insert into tbl_message_tags(tag_id, msg_id) values (1, 1), (0, 1), (1, 2), (0, 3);
After this you can make query like this:
select tag from tbl_tags join (select tag_id from tbl_messages join tbl_message_tags on id = msg_id where msg_id = 1) as t on id = t.tag_id;
Result will be:
----------
| id | tag |
|----|-----|
| 1 | tag0|
|----|-----|
| 2 | tag1|
---- -----
Also, you need to add message identifier field into the tbl-used to get message, linked with every row.
Another variant (not preferable):
You need tbl-tags only if you want to use similar tags in many messages (after receving message, you can normalize case, split it and append only new tags into the tbl-tags), but if you don't need this type of optimization, you can use "array field" in the message table (i.e., in mysql you can do this in the similar way: How can I simulate an array variable in MySQL?).
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! :)
I have 2 tables:
university:
university_id(p.k) | university_name
and user:
uid | name | university_id(f.k)
How to keep university_id NULL in user table?
I am writting only 1 query, my query is:
INSERT INTO user (name, university_id) VALUES ($name, $university_id);
Here $university_id can be null from front end.
university table will be set bydefault by me.
In the front end, student will select the university name, according to that the university_id will pass to user table, but if student is not selecting any university name then is should pass null value to the user table for university_id field.
Just allow column university_id of table user to allow NULL value so you can save nulls.
CREATE TABLE user
(
uid INT NOT NULL,
Name VARCHAR(30) NOT NULL,
university_ID INT NULL, -- <<== this will allow field to accept NULL
CONSTRAINT user_fk FOREIGN KEY (university_ID)
REFERENCES university(university_ID)
)
UPDATE 1
based on your comment, you should be inserting NULL and not ''.
insert into user (name,university_id) values ('harjeet', NULL)
UPDATE 2
$university_id = !empty($university_id) ? "'$university_id'" : "NULL";
insert into user (name,university_id) values ('harjeet', $university_id);
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
Here suppose i have foreign key user_id and i want to insert null value for that.
Checkbox must be checked for insert null value for foreign key.
I was using MySQL InnoDB and even allowing NULL in the FK column and using NULL as default I was getting an error.
So I used the SET syntax:
INSERT INTO (table) SET value1=X...
And I just don't set the FK column.
I've got a mysql database with a table (InnoDB) of Games:
gamerooms
id: bigint(20) unsigned not null auto_increment
PRIMARY KEY (`id`)
I'd like to start generating a UUID value for each row which I can share publicly, something like:
gamerooms
id | id_public |
--------------------
1 | abcde
2 | ghijk
3 | lmnop
...
select * from gamerooms where id_public = ...
How do I add this new column, also keeping in mind that there are already records in the table? I'm confused because the column should be marked NOT NULL, but after adding the column, all records that already exist would have empty values.. Do I have to provide a default value?:
ALTER TABLE `gamerooms` ADD COLUMN `id_public` varchar(36) DEFAULT something AFTER `id`
I want to put an index on id_public of course after it's created, so not sure if null values after the column is first created will mess anything up.
Also, I can use varchar(36) with mysqls UUID() output, right?
Thank you
Your ALTER statement is correct:
ALTER TABLE `gamerooms`
ADD COLUMN `id_public` varchar(36) NOT NULL DEFAULT 'something' AFTER `id`
According to my MySQL Pocket Reference, if you don't provide a default value for a column that is defined as NOT NULL:
MySQL picks a value based on the type of the field
In this case, I'm guessing the default would be empty string. Once your column has been added, simply create a new index for the column, and rebuild the index using a null alteration instruction like so:
CREATE INDEX myIndex ON gamerooms(id_public);
ALTER TABLE gamerooms ENGINE = InnoDB;
You may be able to create the index at the same time you do the insert. My MySQL-fu isn't strong enough to know how to do that.
Should the existing records have a value once you create this new column? If yes, you could do this in multiple steps. First, create the new column without constraint or index and then back populate it with the UUID for all existing records. Once everything is populated, add the not null constraint and your indexes.
As a UUID is a 128-bit number, you don't need a varchar column to store it. a char(16) column would just be ok for saving a UUID binary data.
ALTER TABLE `gamerooms` ADD COLUMN `id_public` char(16) NOT NULL DEFAULT '' AFTER `id`
I need to remove duplicate records (just to keep one copy) from a MySQL table in MyISAM format. I have read many questions in Stackoverflow about similar issues but always the people use an ID field as unique id or similar and I haven't this field because my "Key" could be duplicated. I want to remove rows with the 'Fecha' and 'Equip' duplicated.
CREATE TABLE `pfc` (
`Fecha` datetime NOT NULL,
`Equip` int(10) unsigned NOT NULL,
`Value` double NOT NULL,
KEY `Fecha` (`Fecha`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AVG_ROW_LENGTH=21 ROW_FORMAT=FIXED;
An example table data:
Fecha | Equip | Value
06/02/2011 0:00:11 | 22 | 29.0
06/02/2011 0:22:11 | 22 | 45.3
06/02/2011 0:00:11 | 22 | 29.0
The result should be:
Fecha | Equip | Value
06/02/2011 0:00:11 | 22 | 29.0
06/02/2011 0:22:11 | 22 | 45.3
This structure is not possible to change. I cannot use PRIMARY KEY or UNIQUE INDEX solutions. To create a temporal table without duplicates and then rename would be a poor solutions also, because the KEY and another parameters will be lost.
Thanks
ALTER IGNORE TABLE `pfc` ADD UNIQUE(`Fetcha`, `Equip`);
That will keep the first record it finds and remove duplicates from your table.
From MySQL manual:
IGNORE is a MySQL extension to standard SQL. It controls how ALTER
TABLE works if there are duplicates on unique keys in the new table or
if warnings occur when strict mode is enabled. If IGNORE is not
specified, the copy is aborted and rolled back if duplicate-key errors
occur. If IGNORE is specified, only the first row is used of rows with
duplicates on a unique key. The other conflicting rows are deleted.
Incorrect values are truncated to the closest matching acceptable
value.
Edit:
To create an exact copy of your table, use the following:
CREATE TABLE table_copy SELECT * FROM pfc;
That will copy the table structure and the data. After that, run the ALTER command to add the UNIQUE constraint and filter out the records that are duplicated.
Just as a test, try this to see if it is what you want
CREATE TABLE new_pfc AS
SELECT * FROM pfc GROUP BY fecha, equip
DELETE n1 FROM pfc n1, pfc n2 WHERE n1.Fecha = n2.Fecha AND n1.Equip=n2.Equip AND n1.Value=n2.Value