How to insert into a table join other table using Activerecord in CodeIgniter? - sql

I'm new to CodeIgniter and ORM, I hope you guys can help me with this.
The question table:
CREATE TABLE `question` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(128) NOT NULL DEFAULT '',
`content` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The answer table:
CREATE TABLE `answer` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`question_id` int(11) unsigned NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`),
KEY `question_id` (`question_id`),
CONSTRAINT `answer_ibfk_1` FOREIGN KEY (`question_id`) REFERENCES `question` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The equivalent SQL is:
INSERT INTO answer(content, question_id)
VALUES('Ironman', (select id
from question
where title ='favourite characters'
and content = 'Who is your favourite characters in Avanger?'));
Anyone can tell me how to achieve the same thing but using CodeIgniter Activerecord?

Don't do that, instead use the primary key (id) to insert directly into the base table.

Related

Foreign key constraint is incorrectly formed when import table

I have some question about database structure, laravel orm and constraints.
So first I have some tables(this code is from my DB dump):
CREATE TABLE `person` (
`person_id` int(10) UNSIGNED NOT NULL,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`middle_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `worker` (
`worker_id` int(10) UNSIGNED NOT NULL,
`hire_date` date NOT NULL,
`person_id` int(10) UNSIGNED NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `worker_contract` (
`worker_contract_id` int(10) UNSIGNED NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci,
`worker_id` int(10) UNSIGNED NOT NULL,
`salary` decimal(10,2) NOT NULL,
`worker_id_boss` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `worker_specialty` (
`worker_specialty_id` int(10) UNSIGNED NOT NULL,
`worker_id` int(10) UNSIGNED NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `describe` (
`describe_id` int(10) UNSIGNED NOT NULL,
`person_id` int(10) UNSIGNED DEFAULT NULL,
`describe` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `person`
MODIFY `person_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=47;
ALTER TABLE `worker`
MODIFY `worker_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=45;
ALTER TABLE `worker_contact`
MODIFY `worker_contact_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
ALTER TABLE `describe`
MODIFY `describe_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
ALTER TABLE `person`
ADD PRIMARY KEY (`person_id`);
ALTER TABLE `worker`
ADD PRIMARY KEY (`worker_id`),
ADD KEY `person_id_FK` (`person_id`) USING BTREE;
ALTER TABLE `worker_contract`
ADD PRIMARY KEY (`worker_contract_id`),
ADD KEY `worker_id_FK` (`worker_id`) USING BTREE,
ADD KEY `person_id_boss_foreign` (`person_id_boss`);
ALTER TABLE `describe`
ADD PRIMARY KEY (`describe_id`);
ALTER TABLE `worker_contract`
ADD CONSTRAINT `worker_id_boss_foreign` FOREIGN KEY (`worker_id_boss`) REFERENCES `person` (`person_id`) ON DELETE CASCADE;
ALTER TABLE `describe`
ADD CONSTRAINT `person_id_tag_foreign` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`) ON DELETE SET NULL;
Here is my problem, when I delete person table from databasa and I want to import it without checking foregin key I have #1005 cannot create 'db'.'person' (Errno: 150 "Foreign key constraint is incorrectly formed").
I create migration with Laravels ORM. All id field are the same type and there no mistakes in name fields.
When I remove constraint from DB it works and phpMyAdmin didn't show the relations between models. When I import db dump there is no errors.
When I have describet models in php code, in which place ORM use relations from model class? Only in app place?
When I remove constraints the db efficiency will will get smaller? And is it need?
What I should fix or what here is wrong?
First, disable FOREIGN_KEY_CHECKS
DB::statement('SET FOREIGN_KEY_CHECKS=0;'); // disable
//do your import logic
DB::statement('SET FOREIGN_KEY_CHECKS=1;'); //enable

Constraint on cross-reference table that will check primary key table columns for integrity

I have a cross-reference table which contains two foreign keys. RoleId(PK,FK) and PermissionId(PK,FK). The Role table and the Permission table both contain a foreign key column called ApplicationId. I want to ensure that a record cannot be inserted into the cross-reference table that contains a RoleId associated with ApplicationId 1 and PermissionId associated with ApplicationId 2. Is there any method other than using a trigger to accomplish this type of integrity?
you can add the applicationId column to the cross reference table and then extend the foreign keys of the Role and Permission tables to include the applicationId column . This gives the desired referential integrity .
Here is a worked out schema in mysql
CREATE TABLE `application` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `permission` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`applicationId` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `id_app` (`id`,`applicationID`),
CONSTRAINT `FK_perm_app` FOREIGN KEY (`applicationID`) REFERENCES `application` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `role` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`applicationId` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `id_app` (`id`,`applicationID`),
CONSTRAINT `FK_role_app` FOREIGN KEY (`applicationID`) REFERENCES `application` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `role_permission_application` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`roleID` int(11) unsigned NOT NULL,
`permissionID` int(11) unsigned NOT NULL,
`applicationID` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_role` (`roleID`,`applicationID`),
KEY `FK_permission` (`permissionID`,`applicationID`),
CONSTRAINT `FK_permission` FOREIGN KEY (`permissionID`,`applicationID`) REFERENCES `permission` (`id`,`applicationID`),
CONSTRAINT `FK_role` FOREIGN KEY (`roleID`,`applicationID`) REFERENCES `role` (`id`,`applicationID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Gii CRUD generator and related tables

I am using Yii framework and I have got a problem with CRUD generator.
I have got two tables called Users and news with the following structures:
CREATE TABLE IF NOT EXISTS `news` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`keyword` varchar(1000) COLLATE utf8_persian_ci DEFAULT NULL,
`user_id` tinyint(3) unsigned NOT NULL,
`title` varchar(100) COLLATE utf8_persian_ci DEFAULT NULL,
`body` varchar(1000) COLLATE utf8_persian_ci DEFAULT NULL,
`publishedat` date DEFAULT NULL,
`state` tinyint(1) unsigned DEFAULT NULL,
`archive` tinyint(1) unsigned DEFAULT NULL,
`last_modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `news_FKIndex1` (`keyword`(255)),
KEY `news_FKIndex2` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(128) NOT NULL,
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`lastvisit_at` timestamp NULL DEFAULT NULL,
`is_disabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `status` (`is_disabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
when I generate a CRUD using Gii for my news table I cannot see the fields for users table. Instead of user_id I want to see the username in the table created by CRUD generator. How can I make a change in the code to get the result as above?
First, user_id needs to be a foreign key field not just a key field.
Second, gii will not generate the field as you require by default. For such functionality an extension such as Giix might help. However, since a relation exists you could always use relationName.username to display the username in a grid view or a list view.

I get "a foreign key constraint fails" error when attempting to join two classes/tables

I have these classes, abbreviated for practical reasons:
class CV {
Date dateCreated
static hasMany=[proposals: Proposal]
}
class Proposal {
String name
Date date_started
static hasMany = [CVs: CV]
static belongsTo = CV
}
Grails creates tables for both these classes, and a third class named "cv_proposals" joining them. So far, so good. I have data in both the CV and the Proposal tables, they both have autoincremented "id" values. All good.
in Oracle MySQL Workbench, I try to manually add values to the joining table to get some dummy data to work with. I get an error message with this trace:
ERROR 1452: Cannot add or update a child row: a foreign key constraint fails
(cvreg_utv.cv_proposals, CONSTRAINT FK17D946F55677A672 FOREIGN KEY (cv_id) REFERENCES cv (id))
I made sure both the tables had several lines of data in them, and that I could edit both of them separately.
After trying dropping and recreating the table, altering the classes back and forth, I'm kind of convinced that this operation somehow has to be done through a running Grails application. So I write this script in a controller and run it:
def g = CV.get(1)
Proposal proposal = g.addToProposals(new Proposal(
name: "SavingTest",
date_started: new Date())).save()
I still get the same error, though. Is this not the right way to define a proposal that is connected to a certain CV? Am I wrong in using a many-to-many connection here somehow?
Edit: adding the schema-create script for the joining table
delimiter $$
CREATE TABLE `cv_proposals` (
`proposal_id` bigint(20) NOT NULL,
`cv_id` bigint(20) NOT NULL,
PRIMARY KEY (`cv_id`,`proposal_id`),
KEY `FK17D946F55677A672` (`cv_id`),
KEY `FK17D946F5F7217832` (`proposal_id`),
CONSTRAINT `FK17D946F5F7217832` FOREIGN KEY (`proposal_id`) REFERENCES `proposal` (`id`),
CONSTRAINT `FK17D946F55677A672` FOREIGN KEY (`cv_id`) REFERENCES `cv` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$
And the CV table:
CREATE TABLE `cv` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`user_id` bigint(20) NOT NULL,
`version_name` varchar(255) DEFAULT NULL,
`date_created` datetime NOT NULL,
`last_updated` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `FKC734A9AB992` (`user_id`)
) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1$$
And the Proposal table:
CREATE TABLE `proposal` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`date_ended` datetime NOT NULL,
`date_started` datetime NOT NULL,
`description` varchar(500) DEFAULT NULL,
`name` varchar(500) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1$$
This is the insert script I tried to run:
INSERT INTO `cvreg_utv`.`cv_proposals` (`proposal_id`, `cv_id`)
VALUES ('1', '1');
You crated the tables manually? It's interesting that cv table is using MyISAM engine and the others uses InnoDB.
I think you want to use InnoDB to all your tables, since this engine is transactional. In my test, I also was unable to create the cv_proposals table until I changed the cv creation:
CREATE TABLE cv (
id bigint(20) NOT NULL AUTO_INCREMENT,
version bigint(20) NOT NULL,
user_id bigint(20) NOT NULL,
version_name varchar(255) DEFAULT NULL,
date_created datetime NOT NULL,
last_updated datetime NOT NULL,
PRIMARY KEY (id),
KEY FKC734A9AB992 (user_id)
) ENGINE=InnoDB AUTO_INCREMENT=101
After that, the insert's worked smoothly.

Two n x m relationships with the same table in mysql

I want to create a database in which there's an n x m relationship between the table drug and the table article and an n x m relationship between the table target and the table article.
I get the error: Cannot delete or update a parent row: a foreign key constraint fails
What do I have to change in my code?
DROP TABLE IF EXISTS `textmine`.`article`;
CREATE TABLE `textmine`.`article` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Pubmed ID',
`abstract` blob NOT NULL,
`authors` blob NOT NULL,
`journal` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `textmine`.`drugs`;
CREATE TABLE `textmine`.`drugs` (
`id` int(10) unsigned NOT NULL COMMENT 'This ID is taken from the biosemantics dictionary',
`primaryName` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `textmine`.`targets`;
CREATE TABLE `textmine`.`targets` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`primaryName` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `textmine`.`containstarget`;
CREATE TABLE `textmine`.`containstarget` (
`targetid` int(10) unsigned NOT NULL,
`articleid` int(10) unsigned NOT NULL,
KEY `target` (`targetid`),
KEY `article` (`articleid`),
CONSTRAINT `article` FOREIGN KEY (`articleid`) REFERENCES `article` (`id`),
CONSTRAINT `target` FOREIGN KEY (`targetid`) REFERENCES `targets` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `textmine`.`contiansdrug`;
CREATE TABLE `textmine`.`contiansdrug` (
`drugid` int(10) unsigned NOT NULL,
`articleid` int(10) unsigned NOT NULL,
KEY `drug` (`drugid`),
KEY `article` (`articleid`),
CONSTRAINT `article` FOREIGN KEY (`articleid`) REFERENCES `article` (`id`),
CONSTRAINT `drug` FOREIGN KEY (`drugid`) REFERENCES `drugs` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
You are trying to create tables out of order.
For example you are trying to create contiansdrug table which refers to table drugs before drugs table.
Remember that any SQL, even DDL, tries to leave database in consistent state.
I would recommend putting the commands in proper order. Alternatively you have options to turn off the checks temporarily and run the creation scrip inside transaction, see the instructions here
Relevant section is
SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;
.. your script..
SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
SET AUTOCOMMIT = 1;
EDIT:
OK, try not to have same names for constraints. Reading the fine manual enlightens:
If the CONSTRAINT symbol clause is
given, the symbol value must be unique
in the database. If the clause is not
given, InnoDB creates the name
automatically.
EDIT2:
To spell it out, you have duplicate constrain symbol article, rename it and all will be fine.
Standard practice is if you name your constrains to use names that describe what is related, for example containsdrug_acticelid_article_id (firsttablename_column_secondtablename_column) would be unique and descriptive.
I solved the problem by not declaring the Foreign Key inside of MySql but simply declaring them as ints.