How truncate a table in MySQL that is using ManyToMany field - php

I have a table in MySQL which have a ManyToMany field and I want truncate the table, but when I try it, I obtain the following error:
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint ...
I'm using Symfony with Doctrine but if it is possible, I'm interested in learn how to do it through console
class Project {
/**
* #ORM\ManyToMany(targetEntity="Shipping", mappedBy="projects")
**/
private $employee;
}
class Employee{
/**
* #ORM\ManyToMany(targetEntity="Product", inversedBy="employee")
* #ORM\JoinTable(name="middle_table")
**/
protected $projects;
}

Foreign key means that you have two table and each update must be compatible with the table referred to by the foreign key constraint.
Posible solution is here: How do I truncate tables properly?
SET FOREIGN_KEY_CHECKS = 0; -- Disable foreign key checking.
TRUNCATE TABLE forums;
TRUNCATE TABLE dates;
TRUNCATE TABLE remarks;
SET FOREIGN_KEY_CHECKS = 1; -- Enable foreign key checking.

Now your foreign key in middle_table does not allow you to delete records from Projects table. In other words you have a link to Project in middle_table, it does not give a chance to delete row from Project. So you should change definition of your foreign key to allow deletion, you can set to null the link or make cascade delete. I prefer second option, so change annotation to following, it should allow you to delete rows in Projects table, it also will delete link to Project in middle_table.
class Project {
/**
* #ORM\ManyToMany(targetEntity="Shipping", mappedBy="projects", cascade={"remove"})
**/
private $employee;
}
Documentation:
Doctrine association mapping
mysql foreign key contraint

Related

Payum Symfony Doctrine Can't Create Table

I am trying to add a reference to a profile (called Square) to my Payment model (extension of Payum\Core\Model\ArrayObject), but I can't add a foreign key on the table. I want to do this so that when the payment is processed I can update a field saying that the square is now paid. Here is my setup:
Square.php
/**
* #var integer
*
* #ORM\Column(name="msid", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $msid;
Payment.php
/**
* #ORM\OneToOne(targetEntity="Square")
* #ORM\JoinColumn(name="msid", referencedColumnName="msid")
*/
private $square;
Error Codes:
[Doctrine\DBAL\Exception\DriverException]
An exception occurred while executing 'ALTER TABLE payment ADD CONSTRAINT FK_6D28840D405F5364 FOREIGN KEY (msid) REFERENCES square (msid)':
SQLSTATE[HY000]: General error: 1005 Can't create table 'memorysq_version2.#sql-1658_1487b' (errno: 150)
Several other entities use the msid field to join on, it just isn't working with my Payum Payment model.
[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'memorysq_version2.#sql-1658_1487b' (errno: 150)
[PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'memorysq_version2.#sql-1658_1487b' (errno: 150)
Output of --dump-sql
ALTER TABLE comment ADD CONSTRAINT FK_9474526C405F5364 FOREIGN KEY (msid) REFERENCES square (msid);
ALTER TABLE asset ADD CONSTRAINT FK_2AF5A5C405F5364 FOREIGN KEY (msid) REFERENCES square (msid);
ALTER TABLE payment ADD CONSTRAINT FK_6D28840D405F5364 FOREIGN KEY (msid) REFERENCES square (msid);
ALTER TABLE square ADD CONSTRAINT FK_CDE368A9F132696E FOREIGN KEY (userid) REFERENCES user (userid);
ALTER TABLE square ADD CONSTRAINT FK_CDE368A96AFF851C FOREIGN KEY (squaretype) REFERENCES product (id);
ALTER TABLE square ADD CONSTRAINT FK_CDE368A9DC01AA6E FOREIGN KEY (dualpicture) REFERENCES asset (assetid);
ALTER TABLE square ADD CONSTRAINT FK_CDE368A97F98CD1C FOREIGN KEY (clientid) REFERENCES client (clientid);
ALTER TABLE square ADD CONSTRAINT FK_CDE368A916DB4F89 FOREIGN KEY (picture) REFERENCES asset (assetid);
Several other entities use the msid field to join on, it's just not working with my Payum Payment model. Any help would be greatly appreciated.
The error message actually says that MySQL can't create the foreign key. Since you're executing an ALTER TABLE, the tables should already be there. Since the tables presumably already exist, it could be that there's already some data in the payment table, which isn't in the square table.
Other stuff worth looking into is if both columns have the exact same type (including signed/unsigned) and have a matching collation. On the table level, you could look at if the engine is the same, if the charset is the same and if both tables aren't temporary tables.

Propel follow relationship backwards

I have two tables in my db, that I have reverse engineered with propel reverse, one of which has the other as a foreign key. Here is part of the sql used to create the answer table:
CREATE TABLE answer (
id INT AUTO_INCREMENT PRIMARY KEY,
run_id INT NOT NULL,
FOREIGN KEY (run_id)
REFERENCES run(id)
ON UPDATE CASCADE
ON DELETE CASCADE
);
Now I am creating a method in RunQuery that has to join on the Answer table:
RunQuery::create()->join('Answer')
I get error:
Uncaught exception 'PropelException' with message 'Unknown relation Answer on the Run table'
In the Apache logs
I've looked in the generated schema, and it lists run as a foreign key of answer... How do I make this join happen?
Cheers,
-Scott!
Propel should have generated joinAnswer() and joinWithAnswer() methods (join with will hydrate your result object), but sometimes i have to use the table name instead of the phpName that you're trying to use, so, RunQuery::create()->join('answer') should do the trick.

Symfony Cannot Execute Doctrine Schema Update

I am having an issue running doctrine:schema:update --force because of a forgeign key constraint issue.
[Doctrine\DBAL\DBALException] An exception occurred while executing 'ALTER TABLE Product ADD CONSTRAINT FK_1CF73D312ADD6D8C FOREIGN KEY (supplier_id) REFERENCES Supplier (id) ON DELETE SET NULL':
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`wic_dev`.`#sql-5c0 a_1a12`, CONSTRAINT `FK_1CF73D312ADD6D8C` FOREIGN KEY (`supplier_id`) REFERENCES `Supplier` (`id`) ON DELETE SET NULL)
[PDOException] SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`wic_dev`.`#sql-5c0 a_1a12`, CONSTRAINT `FK_1CF73D312ADD6D8C` FOREIGN KEY (`supplier_id`) REFERENCES `Supplier` (`id`) ON DELETE SET NULL)
I have two tables that are creating this error: Products and Suppliers.
Products can have 1 supplier and suppliers can have many products.
Here is how I have my entities set up:
Product Entity:
/**
* #ORM\ManyToOne(targetEntity="WIC\SupplierBundle\Entity\Supplier", inversedBy="products", fetch="EAGER")
* #ORM\JoinColumn(name="supplier_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
* #Common\Versioned
* #Assert\NotBlank(message="Supplier Cannot Be Blank")
*/
protected $supplier;
Supplier Entity
/**
* #ORM\OneToMany(targetEntity="WIC\ProductBundle\Entity\Product", mappedBy="supplier", cascade={"all"})
*/
protected $products;
I currently have data in each table. I know some products are missing a supplier and suppliers are missing products.
What am I doing wrong and how can I fix this issue? I need to run this schema update so that my other tables will get updated as well.
Thanks so much for your help!
Here is how I fixed the issue. In my products table I was storing values as "0" if the supplier wasnt found. Because it was a manytoone and onetomany relationship between the two tables, it was having a conflict because supplier_id is never 0, 0 does not match any id in the suppliers table. I had to update the products table to set any value for 0 to NULL, this made the schema update work.
In most cases, it's a simple autoloading problem
In most cases, simply make sure you have a use statement for the entity you're trying to create a relationship with.
This happens often when the 2 entities are not in the same bundle and therefore need to autoload them. For the error to disappear, simply do this:
In your product entity, don't forget:
use WIC\SupplierBundle\Entity\Supplier;

How to specify foreign key column for Class Table Inheritance in Doctrine2?

How can I specify the columns that are used for the foreign key relation with Class Table Inheritance in Doctrine 2? For example, take the following two classes:
/**
* #Entity
* #InhertanceType("JOINED")
* #DiscriminatorColumn(name="type", type="string")
* #DiscriminatorMap("person" = "Person", "employee" = "Employee")
*/
class Person
{
/** #Id */
public $id;
/** #Column(type="string") */
public $ssn;
}
/** #Entity */
class Employee
{
/** #Column(type="decimal") */
public $salary;
}
With this, Doctrine expects a table structure somewhat along this:
CREATE TABLE `person` (
`id` INT(11) NOT NULL auto_increment,
`ssn` VARCHAR(255) default NULL,
PRIMARY_KEY(`id`)
)
CREATE TABLE `employee` (
`person_id` INT(11) NOT NULL,
`salary` DECIMAL(10,2) default NULL,
PRIMARY_KEY(`person_id`)
)
ALTER TABLE `employee`
ADD CONSTRAINT `person_fk` FOREIGN KEY (`person_id`)
REFERENCES `person` (`id`) ON DELETE CASCADE
There is a foreign key employee.person_id that points to person.id. But how can I tell Doctrine which columns to use? I assume that the person.id reference comes from the #Id annotation on the Person class, but what if I want to create the FK to person.ssn instead (it's conceivable, since SSN are naturally unique).
And what if I have a legacy database where employee.person_id is called employee.p_id instead?
First of all, you are missing the "extends Person" in the Employee class definition.
From what I know, when you are doing this type of inheritance, doctrine uses the primary key in the main class to join all other tables, its is expected behavior.
When you do a query, doctrine will join all the child tables to the parent and then hydrate according to the discriminator map. With that in mind, it doesn't matter if your primary key is an automatically incremental id or a unique field. If you have ssn defined in the parent class, it will be available for searching in all your subclasses.
So a couple of tips here. You can if you want, remove the automatical id and use ssn as your primary key, then doctrine expects that all of your child tables to have that same field defined in them. For performance it may be wise to have an integer instead of a 255 string to do the joins anyway.
If you want to mantain the automated id, you may want to add a unique index to the parent class, that way if you access the classes by that field, you wont get performance slowdowns.
If you want to have the class name to be something and the table name to be something else, use this
/** #Id #Column(name="p_id") */
public $id;
But then remember that all the tables that are part of the inheritance should use that name.
Moreover, I normally use doctrine for mapping an existing database and extending it (migrate to doctrine), and if I'm adding a new feature and the model requires so, I create the mapping and tables myself keeping in mind how Doctrines inheritance works. But if you have existing tables that think can be modeled with Inheritance, expect some trouble, and maybe the needs to modify the existing tables.
Hope this helps.

Need help understanding Doctrine one to many

Referencing doctrine reference - one to many unidirectional
class User
{
// ...
/**
* #ManyToMany(targetEntity="Phonenumber")
* #JoinTable(name="users_phonenumbers",
* joinColumns={#JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="phonenumber_id", referencedColumnName="id", unique=true)}
* )
*/
private $phonenumbers;
// ...
}
The part I don't understand is unique=true. What does it do? The way I read it is ...
User has a Many to Many relationship with Phonenumber
it uses the join table users_phonenumbers
users_phonenumbers.user_id = users.id
users_phonenumbers.phonenumber_id = Phonenumber.id
and I guess the unique does something to constraints a many to many to a many to one relationship somehow. But how do you explain it? Also in a SQL sense (what is the output like)?
The mapping translates into the following SQL tables (assuming both have a surrogate ID, called id):
CREATE TABLE User (id INT(10) PRIMARY KEY)
CREATE TABLE Phonenumber (id INT(10) PRIMARY KEY)
CREATE TABLE User_Phonenumber (
user_id INT(10),
phonenumber_id INT(10),
PRIMARY KEY (user_id, phonenumber_id),
UNIQUE(phonenumber_id)
);
What this means in terms of your code:
$phonenumber = new Phonenumber();
$phonenumber->setNumber("123-4567890");
$user1->addPhonenumber($phonenumber);
$user2->addPhonenumber($phonenumber);
$entityManager->flush();
This would throw a unique constraint exception, you cannot add the same phonenumber to different users, because phonenumbers are unique (on the database level).
The unique constraints ensure that data contained in a column or a group of columns is
unique.
Be aware, two null values are NOT considered equal, so you can store two or more duplicate rows. The primary key is already unique, so you don't need to use for primary key columns. :)
P.

Categories