Copy rows in the same table with recursive dependency inside - mysql

I have the some tables in MySQL database
create table pages
(
id bigint not null,
organization_id bigint null,
parent_id bigint null,
language_tag varchar(2) null,
type varchar(7) null,
theme varchar(19) null,
status varchar(7) null,
title varchar(256) null,
image text null,
image_hover text null,
sort int null,
created_at timestamp null,
updated_at timestamp null,
constraint pages_id_uindex
unique (id),
constraint pages_pages_id_fk
foreign key (parent_id) references pages (id)
on update cascade on delete cascade
);
create table blocks
(
id bigint null,
page_id bigint null,
title varchar(256) null,
content longtext null,
readmore longtext null,
image varchar(1024) null,
image_hover varchar(1024) null,
type char(9) null,
sort int null,
constraint blocks_pages_null_fk
foreign key (page_id) references pages (id)
);
As you can see parent_id is a reference to its own table id.
I want to copy some specific rows with all its children. I couldn't write a simple insert query because I cannot know parent_id of parent page that not existing yet. Also, relation is recursive and not plain. Some children could have another children, e.t.c Just like a tree. I could make it nullable, but then I have to update all children manually. And I have blocks relation entity that have to be copied too. It's a quite terrible amount of work. Could you give me advice how I can resolve this issue with the simplest way?

Related

I have a child table that depends on two parent tables that are not related. i want to insert rows into child table

I am creating a database for selling houses.
I have a parent table that I am calling location that has three columns :
locationLat : the latitude of location of property
locationLong : the longitude of the property
locationName : an alternative name that i can use to identify the location of the property by name
Both locationLat and locationlong make up a composite primary key of this table.
Then I have a child table called houseToLet, this table only stores the houses that are for letting. I have similar different tables houseToBuy, fullyFurnished, landtoSell etc. The table for houseTolet has a composite primary key like the location table above i.e locationLat, locationLong and a foreign composite key location_locationLat and location_locationLong that references the location table.
Then I have another table called generalFeatures. This the table where I store general features of all the properties I am selling. So generalFeatures table is a child table of houseTolet and Housetobuy as well as Fullyfurnished tables,
When I insert rows into the location table, I find no problem as it is the parent table. When i insert rows into houseTolet table I find no problem since it is a child table and I will have inserted the parent location table already. However when I insert into the generalFeatures table I get into problem since it is a child table of housetoBuy as well as other tables including Fullyfurnished.
Please assist me to know how I can do this.
CREATE TABLE IF NOT EXISTS `foreign`.`location` (
`locationLat` DECIMAL(10,8) NOT NULL,
`locationLong` DECIMAL(11,8) NOT NULL,
`locationName` VARCHAR(35) NOT NULL,
PRIMARY KEY (`locationLat`, `locationLong`))
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS `location`.`housetolet` (
`locationLat` DECIMAL(10,8) NOT NULL,
`locationLong` DECIMAL(11,8) NOT NULL,
`type` ENUM('gatedCommunity', 'standalone', 'apartment') NOT NULL,
`location_locationLat` DECIMAL(10,8) NOT NULL,
`location_locationLong` DECIMAL(11,8) NOT NULL,
PRIMARY KEY (`locationLat`, `locationLong`),
INDEX `fk_housetolet_location_idx` (`location_locationLat` ASC, `location_locationLong` ASC))
CREATE TABLE IF NOT EXISTS `foreign`.`generalfeatures` (
`locationLat` DECIMAL(10,8) NOT NULL,
`locationLong` DECIMAL(11,8) NOT NULL,
`livingAreaAndSize` INT NOT NULL,
`bedrooms` TINYINT(4) NOT NULL,
`bathrooms` TINYINT(4) NOT NULL,
`masterEnsuite` TINYINT(1) NOT NULL,
`bedroomsWithBathrooms` TINYINT(4) NOT NULL,
`kitchenAndSize` TINYINT(4) NOT NULL,
`parkingAndSlots` TINYINT(4) NOT NULL,
`swimmingPool` TINYINT(1) NOT NULL,
`liftsAndNumber` TINYINT(4) NOT NULL,
`CCTV` TINYINT(1) NOT NULL,
`sizeOfLand` INT(11) NOT NULL,
`borehole` TINYINT(1) NOT NULL,
`housetobuy_locationLat` DECIMAL(10,8) NOT NULL,
`housetobuy_locationLong` DECIMAL(11,8) NOT NULL,
`housetolet_locationLat` DECIMAL(10,8) NOT NULL,
`housetolet_locationLong` DECIMAL(11,8) NOT NULL,
`fullyfurnished_locationLat` DECIMAL(10,8) NOT NULL,
`fullyfurnished_locationLong` DECIMAL(11,8) NOT NULL,
PRIMARY KEY (`locationLat`, `locationLong`),
INDEX `fk_generalfeatures_housetobuy1_idx` (`housetobuy_locationLat` ASC, `housetobuy_locationLong` ASC),
INDEX `fk_generalfeatures_housetolet1_idx` (`housetolet_locationLat` ASC, `housetolet_locationLong` ASC),
INDEX `fk_generalfeatures_fullyfurnished1_idx` (`fullyfurnished_locationLat` ASC, `fullyfurnished_locationLong` ASC),
CONSTRAINT `fk_generalfeatures_housetobuy1`
FOREIGN KEY (`housetobuy_locationLat` , `housetobuy_locationLong`)
REFERENCES `foreign`.`housetobuy` (`locationLat` , `locationLong`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_generalfeatures_housetolet1`
FOREIGN KEY (`housetolet_locationLat` , `housetolet_locationLong`)
REFERENCES `foreign`.`housetolet` (`locationLat` , `locationLong`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_generalfeatures_fullyfurnished1`
FOREIGN KEY (`fullyfurnished_locationLat` , `fullyfurnished_locationLong`)
REFERENCES `foreign`.`fullyfurnished` (`locationLat` , `locationLong`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
I want to be able to insert rows into generalFeatures table for houses to Let without getting foreign key constraints that I need to update other tables like houseTobuy or fullyFurnished first, this is because in a particular instance I will be updating a particular type of a house only but not many options. A house to let cannot be at the same time be a house to buy in my case.
Your database design has flaws. Namely, you are storing in multiple tables information that could be represented as a single record. As it is, it looks like all tables could be merged into main table locations :
the house* tables (houseToLet, houseToBuy, ...) are just there to store the current status of the location (to let, to buy, ...) : this could be represented as an ENUM field in the location table (or as several boolean columns if more than one status can be enabled at a time)
the generalFeatures table also seems to contain a single record for each location, hence all of its fields could be moved to the location table.
Using a single table appears like the right design for your use case (and it sure avoids issues with foreign constraints...).
Other considerations : use an autoincremented integer as primary key instead of a composite key (for this, you can create a UNIQUE constraint).
Here is a sample DDL for your table :
CREATE TABLE IF NOT EXISTS `foreign`.`location` (
-- primary key
`id` INT AUTO_INCREMENT,
PRIMARY KEY (`id`),
-- original columns
`locationLat` DECIMAL(10,8) NOT NULL,
`locationLong` DECIMAL(11,8) NOT NULL,
`locationName` VARCHAR(35) NOT NULL,
-- house status
`status` ENUM('toLet', 'houseToBuy', 'fullyFurnished', 'landtoSell') NOT NULL,
-- columns from `generalfeatures`
`livingAreaAndSize` INT NOT NULL,
`bedrooms` TINYINT(4) NOT NULL,
`bathrooms` TINYINT(4) NOT NULL,
`masterEnsuite` TINYINT(1) NOT NULL,
`bedroomsWithBathrooms` TINYINT(4) NOT NULL
-- other columns from `generalfeatures`...
)ENGINE = INNODB;

How to set primary key with auto increment in MYSQL

CREATE TABLE `journal` (
`yearr` int(4) NOT NULL,
`monthh` char(3) NOT NULL,
`volume` int(4) NOT NULL,
`issue` int(4) NOT NULL,
`pagefromto` varchar(10) NOT NULL,
`pissn` varchar(20) NOT NULL,
`eissn` varchar(20) DEFAULT NULL,
`name` varchar(50) NOT NULL,
`author1` varchar(10) DEFAULT NULL,
`author2` varchar(10) DEFAULT NULL,
`doc` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
)
ALTER TABLE `journal`
ADD PRIMARY KEY (`yearr`,`volume`,`issue`,`pagefromto`,`pissn`);
I need to add another key with auto increment to the above table structure
Your question is a bit confusing. You say you want to add a second primary key which will be auto increment... This doesn't make sense. They are called PRIMARY keys for a reason. There is only one primary key on a table as it is the, well, Primary key.
What I think you want to do is have a auto increment ID to use as the PK, which you could include in your create table like Arshad answered.
At that point, what you want to do is use your auto increment ID as the primary key (the same way you did with your PK, but put only the new ID in the PK, not the rest of your fields.), and you will want to use a unique index to make sure the combination of (yearr,volume,issue,pagefromto,pissn) doesn't repeat.
See this document to get more info on index creation
Note that if your table is already created, you'll have to delete the old primary key before you can add it on the ID.
You can use this query. This will create table with "id" as AutoIncrement and primary key
CREATE TABLE
tbl_employee (
id int(11) NOT NULL AUTO_INCREMENT,
employee_id int(4) NOT NULL,
employee_no int(6) NOT NULL,
employee_name varchar(60) NOT NULL,
department_id int(4) NOT NULL,
designation_id int(4) NOT NULL,
hired_date date NOT NULL,
salary int(10) NOT NULL,
PRIMARY KEY(id)
)

Using composite key as a foreign key in mysql

My Tables
Fee Table
CREATE TABLE IF NOT EXISTS `fee` (
`feeNumber` int(11) NOT NULL,
`feeName` varchar(255) NOT NULL,
`feeDescription` varchar(255) DEFAULT NULL,
`feeAmount` varchar(255) NOT NULL,
`universityName` varchar(255) NOT NULL
)
ADD PRIMARY KEY (`feeNumber`,`feeName`,`feeAmount`)
Housing Table
CREATE TABLE IF NOT EXISTS `housing` (
`housingOfficeNumber` int(11) NOT NULL,
`housingOfficeName` varchar(50) NOT NULL DEFAULT '',
`housingOfficeType` varchar(50) DEFAULT NULL,
`housingOfficePhone` decimal(18,0) DEFAULT NULL,
`housingOfficeRoomDeposit` varchar(50) DEFAULT NULL,
`studentStatusName` varchar(50) DEFAULT NULL,
`housingFeeNumber` int(11) NOT NULL,
`housingFeeName` varchar(255) NOT NULL,
`housingFee` int(255) DEFAULT NULL,
`hOffTrm` varchar(50) DEFAULT NULL,
`universityName` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
What I'm trying to do is reference the feeAmount,feeNumber, and feeName from the fee table and add it to the housingfee, housingfeeName, and housingFeenumber columns in the housing table. Since the feeAmount and feeName columns are not unique I decided to make a composite key out of feeNumber, feeName, and feeAmount. The only part of the composite key I really need referenced is feeAmount. feeName and feeNumber are not really important. using phpmyadmin.
No, no, no. In general, I think it is best to avoid compound primary keys. In this case, in particular, you do not want the fee amount or name to be part of the key. In order to access the row, you need to know the amount. That seems very difficult to implement.
I am guessing that an auto incremented primary key will work just fine. You can then add a separate unique constraint on other columns. So:
CREATE TABLE IF NOT EXISTS `fee` (
`feeNumber` int(11) NOT NULL auto_increment primary key,
`feeName` varchar(255) NOT NULL,
`feeDescription` varchar(255) DEFAULT NULL,
`feeAmount` varchar(255) NOT NULL,
`universityName` varchar(255) NOT NULL,
unique (feeName)
);
Then, another table would have feeNumber with an appropriate foreign key reference. Through the reference, you can get other information -- such as the name and amount -- using a join.

MySQL autoincrement increasing by more than +1 per record

I'm planning a database design for an online store and having an issue with the customer table. I've set a PK and I'm testing by inputting some dummy data. Problem is that when I insert a new row it's not autoincrementing with +1 but more a case of 2,5,7 on the ID.
SQL is:
CREATE TABLE IF NOT EXISTS `foundation`.`Customer`
( `CustomerID` INT NOT NULL AUTO_INCREMENT,
`CustomerFirstName` VARCHAR(20) NULL,
`CustomerLastName` VARCHAR(32) NULL,
`CustomerUsername` VARCHAR(20) NULL,
`CustomerPassword` VARCHAR(32) NULL,
`CustomerEmail` VARCHAR(100) NULL,
`CustomerEmailVerified` TINYINT(1) NULL,
`CustomerRegisteredDate` DATETIME NULL,
`CustomerActive` TINYINT(1) NULL,
`CustomerNewsletterSubscribed` TINYINT(1) NULL,
`CustomerDescription` TEXT NULL,
`CustomerType_CustomerTypeID` INT NOT NULL,
PRIMARY KEY (`CustomerID`),
UNIQUE INDEX `Username_UNIQUE` (`CustomerUsername` ASC),
INDEX `fk_Customer_CustomerType1_idx` (`CustomerType_CustomerTypeID` ASC),
CONSTRAINT `fk_Customer_CustomerType1`
FOREIGN KEY (`CustomerType_CustomerTypeID`)
REFERENCES `foundation`.`CustomerType` (`CustomerTypeID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE = InnoDB;
Check the following system variable, auto_increment_increment it should be 1. If not then it'll increment by the value in it.
show variable like '%auto_increment%'
Also check if you are incrementing manually in the insert query.

How to make a field in a table reference to another table in MySQL/MariaDB?

Say I'm setting up an small database with just 2 tables: feeds and feeditems.
In one table I'd store the feedname and url, with an ID as unique key.
In the second table I'd like to store some info coming from feed items (in example: date, title, url of the item and feedname). But instead of storing the feed name, I'd like to reference this feed field to the ID of that feed in the first table.
Thanks
this a quick example of how to achieve your requirement...
CREATE TABLE IF NOT EXISTS `feeds` (
`Feed_ID` int(11) NOT NULL,
`Feed_Name` varchar(32) NOT NULL,
`Feed_Url` varchar(255) NOT NULL,
PRIMARY KEY (`Feed_ID`)
)
CREATE TABLE IF NOT EXISTS `feeditems` (
`FeedItem_ID` int(11) NOT NULL,
`Feed_ID` int(11) NOT NULL,
`FeedItem_Date` datetime NOT NULL,
`FeedItem_Title` varchar(255) NOT NULL,
`FeedItem_Url` varchar(255) NOT NULL,
`FeedItem_Name` varchar(255) NOT NULL,
PRIMARY KEY (`FeedItem_ID`),
FOREIGN KEY (`Feed_ID`) REFERENCES `feeds`(`Feed_ID`)
ON DELETE CASCADE
)