Insert multi-dimensional data into tables using only MySQL code - mysql

I'm exploring the possibility of using mysql procedures to do insert statements of json objects that embed other json objects. Let's say I created these two mysql tables:
CREATE TABLE `student` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`birth_date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `course` (
`course_id` int(11) unsigned NOT NULL,
`student_id` int(11) unsigned NOT NULL,
`enrollment_date` date NOT NULL,
CONSTRAINT `courses_ibfk_1` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And let's say I'm receiving the following JSON object which I intend to transform and insert into the student and course table:
let payload = [
{
name:"Alice",
birth_date:"1968-01-28",
courses:[
{course_id:4325,enrollment_date:"2018-05-01"},
{course_id:3119,enrollment_date:"2018-09-01"},
{course_id:1302,enrollment_date:"2018-01-01"},
],
},
{
name:"Bob",
birth_date:"1971-10-01",
courses:[
{course_id:2000,enrollment_date:"2018-09-01"},
{course_id:3109,enrollment_date:"2018-09-01"},
{course_id:4305,enrollment_date:"2018-09-01"},
],
},
];
In the past, I would insert the json data using client side code that does something like this
foreach (payload as student) {
studentId = exec_prepared_statement("INSERT INTO student SET name= ?, birth_date = ?",student.name,student.birth_date)
foreach(student.courses as course){
courseId = exec_prepared_statement("INSERT INTO course SET student_id = ?, course_id = ?, enrollment_date = ?",studentId, course.course_id,course.enrollment_date)
}
}
But I'm not sure how to achieve this series of insert behaviour using purely MySQL code because I'm not sure how to pass multi-dimensional data into a mysql stored procedure. It will be great if I can see an example of that somewhere.
Alternatively, someone can tell me if I should completely avoid trying to insert multi-dimensional data via purely MySQL code...that I should have client-side code like PHP, Go, JS do the job? I'd really like to see what this would look like with just MySQL so I can compare which one is more maintainable.

Related

Transform column data into JSON column data using hybrid database

Working with hybrid databases, the point is to extract data from any column of a table, and transform it into another column using JSON format. This is being done into a PostgreSQL database.
Practical example, we have two tables:
CREATE TABLE `avion` (
`id` bigint NOT NULL,
`fabricante` varchar(255) DEFAULT NULL,
`revisiones_json` DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `avion` VALUES (1,'Airbus'),(2,'Boeing');
CREATE TABLE `revision` (
`id` bigint NOT NULL,
`avion_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKepufjqvypljnk6si1dhtdcn3r` (`avion_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `revision` VALUES (1,1),(2,2),(3,2);
We want to obtain for each "Avion" entity, its "revision" related ids, and insert them into a JSON field called "revisiones_json" contained in "Avion" entity.
I'm trying to convert with a subquery the list of related "Revision" entity ids into an array, and set them converting into a JSON_OBJECT, but it's not working. So my question is, someone knows why this conversion its not being made? Some quote misspelling?
This is used query for update:
update avion a1
set a1.revisiones_json = JSON_OBJECT('id',
SELECT JSON_ARRAYAGG(r.id) as ids from
avion a inner join revision r on a.id = r.avion_id
where a.id = a1.id
)
where a1.id > 0;

Field 'category_id' doesn't have a default value MySQL

I'm learning SQL.
I'm trying to insert data. My MySQL database looks like this.
CREATE TABLE category (
category_id CHAR(100),
category_name VARCHAR(120) NOT NULL,
PRIMARY KEY (category_id)
)
I ran this command
INSERT INTO category (category_name) VALUES ("test");
But I got this error
ERROR 1364 (HY000): Field 'category_id' doesn't have a default value
Thank you in advance.
If you want to have an incrementing ID it would need to be an int. You Generally want to make ID's integers not chars to speed up lookup regardless.
CREATE TABLE IF NOT EXISTS category (
`category_id` INT NOT NULL AUTO_INCREMENT,
`category_name` VARCHAR(120) NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET = utf8mb4 COLLATE utf8mb4_unicode_ci;
That will let you insert without adding your own ID, and automatically generate unique ID's for the records.
Issue was you set your category_id field to not have a default value and also not allow null, which means you -have- to set a value for it in the insert. If you wanted to use your existing table you would need to do this:
INSERT INTO category (category_id, category_name) VALUES ("someid", "test");

How to insert a vector into a column of a table in mysql?

In R, I have a vector, "myVector", of strings which I want to insert into a column, "myColumn", of a mysql table, "myTable". I understand I can write the sql query and run it in R using dbSendQuery. So let's figure out the sql query first. Here is an example:
myVector = c("hi","I", "am")
Let's insert myVector in the column myColumn of myTable, row numbers 3 to 5, here is the sql query which works except for the last line I have no idea:
UPDATE myTable t JOIN
(SELECT id
FROM myTable tt
LIMIT 3, 3
) tt
ON tt.id = t.id
SET myColumn = myVector;
Thanks
Assuming that I understand your problem correctly, I have two possible solutions on my mind:
1. one column per element:
if your vectors are all have equal number of elements, you could store each of them in a seperate column. Proceeding from your example above, the table could look like this. (the size of the columns and whether to allow null values or not depends on your data)
CREATE TABLE `myTable` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`element1` varchar(255) DEFAULT NULL,
`element2` varchar(255) DEFAULT NULL,
`element3` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The statement for inserting your vector from above would be:
INSERT INTO `myTable` (`id`, `element1`, `element2`, `element3`)
VALUES (1, 'hi', 'I', 'am');
Depending on how much elements your vectors have this approach might be more or less applicable.
2. Storing the vector as a blob:
Another approach could be storing the vector as a blob. Blob (Binary Large Object) is a datatype to store a variable amount of (binary) data (see: https://dev.mysql.com/doc/refman/5.7/en/blob.html). This idea is taken from this article: http://jfaganuk.github.io/2015/01/12/storing-r-objects-in-sqlite-tables/
The table could be created using the following statement:
CREATE TABLE `myTable` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`myVector` blob,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
When inserting your vector you bind the variable to your query. As I am not a R specialist I would refer to this article for the implementation details.
I'm not aware, if MySQL support Vector data type, but you could design your table as workaround where Vector can be store in different table and will have relation with myTable as 1-M.
This is help you to manage and retrieve details easily. So, assuming myTable is your table and it's existing design is :
myTable
-------
id
col1
vectorCol
So, you main table can be
CREATE TABLE myTable (
id INT NOT NULL AUTO_INCREMENT,
col1 varchar(50),
PRIMARY KEY (id)
);
and table which will store your vector.
CREATE TABLE vectorTab (
id INT NOT NULL AUTO_INCREMENT, -- in case ordering matter
parent_id INT NOT NULL,
value TEXT,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES myTable (id) ON DELETE CASCADE ON UPDATE CASCADE
);
What you should do is export your R vector as JSON using toJSON() function for example:
myJSONVector = toJSON(c("hi","I", "am"))
Also create or alter myTable so that myColumn has the appropriate JSON Data Type
Attempting to insert a value into a JSON column succeeds if the value
is a valid JSON value, but fails if it is not:
Example
CREATE TABLE `myTable` (`myColumn` JSON);
INSERT INTO `myTable` VALUES(myJSONVector); // will fail if myJSONVector is not valid JSON
// update query would be
UPDATE `myTable` SET `myColumn` = myJSONVector
WHERE `id` IN (3,4,5);
In addition
you can make an R vector from JSON using function fromJSON().

How can I unit test for MySQL database with Play 2.x?

I need to test if my code creates the correct database statements. I know I can run my application with an in memory database. It's not perfect, but enough for this project. My SQL contains MySQL specific stuff.
When I run my test it breaks on the evolution that contains the following:
CREATE TABLE `Beaches` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB;
COLLATE='utf8_general_ci'
How to solve the problems with the MySQL specific syntax?
I found a way to get around (most) of the MySQL specific stuff (question 1.)
running(FakeApplication(additionalConfiguration =
inMemoryDatabase(options=Map("MODE" -> "MySQL")))) {
DB.withConnection { implicit c =>
SQL("""
CREATE TABLE `Beaches` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
)
/*! ENGINE=InnoDB; */
/*! COLLATE='utf8_general_ci' */
"""
).execute()
ok
}
}
Note that H2 has a MODE=MySQL as described in the Working with the in-memory H2 database section of the Play documentation.
The other part are the c-style comments as described in the Comment Syntax section of the MySQL documentation.

how to prevent of duplicating records in mysql insertion queries?

i always in inserting data into a mysql table i use a select for that data before inserting to avoid duplicate records and if the query return null then i insert record.
but i think maybe it is not a professional way to do this job.
would you let me the ways you do?
if the reason you don't wish to use primary keys, or unique indexes is because of the error this will generate (which is an issue if you are inserting multiple rows on a single query), you can use the following syntax
insert ignore into [tablename] () VALUES ()
You can also use ON DUPLICATE KEY UPDATE as in to update certain fields as well.
insert into [tablename] () VALUES () ON DUPLICATE KEY UPDATE
for more information, have a look at http://dev.mysql.com/doc/refman/5.1/en/insert.html
You can try the following example. I would suggest you to try this first in your testing environment then you can implement this in your actual scenario.
Follow the below steps:
Step 1: create a table
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`email` varchar(50) NOT NULL,
`password` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Step 2: Run this query multiple times and check that only one row is inserted
INSERT INTO `student` ( `name`, `age`)
SELECT `name`, `age` FROM `student`
WHERE NOT EXISTS (SELECT 1
FROM `student`
WHERE `name` = 'manish'
AND `age` = '23'
);
The "professional" way to do this will be using a primary key constraint.
$qry="INSERT username INTO users";
if(!mysql_query($qry))
{
if(mysql_errno()=1062)
{
echo 'Unique costraint violation!';
}
else
{
//other error
}
}