hi i have a problem when adding unique constraint creation to my change log. in logs it shows the liquibase is reading change sets but i still cant find the unique constraint through query . the problem is it is only applied when i recreate database it doesn't work if table exists before.
<changeSet id="20220524-1" author="Saba Mosleh">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">
SELECT DISTINCT count(CONSTRAINT_NAME) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE
TABLE_NAME = 'voucher_codes' AND CONSTRAINT_TYPE = 'UNIQUE' and CONSTRAINT_NAME = 'unique_voucher_code';
</sqlCheck>
</preConditions>
<addUniqueConstraint tableName="voucher_codes" columnNames="code" constraintName="unique_voucher_code"/>
</changeSet
a table DATABASECHANGELOG is created by liquibase delete your changelog record so liquibase will execute your change log when you restart the application,
or simply add
<addUniqueConstraint
tableName="voucher_codes"
columnNames="code"
constraintName="unique_voucher_code"
runAlways="true"/>
to execute the statement every time.
Related
I have a script to update a database by checking for a foreign key's existence and, if it doesn't exist, creating it. It was generated by SQL Management Studio.
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_tblChangeRequestForecast_tblCostingCenter]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblChangeRequestForecast]'))
ALTER TABLE [dbo].[tblChangeRequestForecast] WITH CHECK ADD CONSTRAINT [FK_tblChangeRequestForecast_tblCostingCenter] FOREIGN KEY([CostingCenterID])
REFERENCES [dbo].[tblCostingCenter] ([CostingCenterID])
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_tblChangeRequestForecast_tblCostingCenter]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblChangeRequestForecast]'))
ALTER TABLE [dbo].[tblChangeRequestForecast] CHECK CONSTRAINT [FK_tblChangeRequestForecast_tblCostingCenter]
GO
The script raises an error when it's run:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_tblChangeRequestForecast_tblCostingCenter". The conflict occurred in database "mydatabase", table "dbo.tblCostingCenter", column 'CostingCenterID'.
This is very mysterious. There is no trace of the foreign key as far as the queries can tell, but the create script fails with the above error. The server is running SQL Server 2005 SP3 (9.00.4035.00).
[Update]: I've just reproduced the issue on a SQL Server 2012 instance. So the version doesn't appear to be too important.
Any idea what could cause this?
It is complaining about the FK constraint that you are trying to add because there is existing data in the table that would no longer be valid if the constraint was successfully applied.
Probably means there is one or more ChangeRequestForecast records where CostingCenterID has a value that doesn't correspond with CostingCenter.CostingCenterID.
Open up SSMS, go to that database, expand that table, and look in the Constraints section. There likely is one in there called "FK_tblChangeRequestForecast_tblCostingCenter" that you need to figure out if you need, and if not, delete it.
I get the following message even when the table that references it is empty: "Cannot truncate table 'dbo.Link' because it is being referenced by a FOREIGN KEY constraint" Doesn't seem to make much sense why this is occurring. Any suggestions?
In SQL Server a table referenced by a FK cannot currently be truncated even if all referencing tables are empty or the foreign keys are disabled.
You need to use DELETE (may require much more logging) or drop the relationship(s) prior to using TRUNCATE and recreate them afterwards or see the workarounds on this connect item for a way of achieving this using ALTER TABLE ... SWITCH
You cannot truncate a table which has an FK constraint on it. As workaround, you could:
1/ Drop the constraints
2/ Trunc the table
3/ Recreate the constraints.
Here it is the associated T-SQL script, supposing you have 2 tables called MyTable and MyReferencedTable:
-- Remove constraint
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_MyReferencedTable_MyTable')
BEGIN
ALTER TABLE dbo.MyReferencedTable
DROP CONSTRAINT FK_MyReferencedTable_MyTable
END
-- Truncate table
TRUNCATE TABLE dbo.MyTable
-- Re-Add constraint
IF NOT EXISTS(SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_MyReferencedTable_MyTable')
BEGIN
ALTER TABLE dbo.MyReferencedTable
WITH CHECK ADD CONSTRAINT [FK_MyReferencedTable_MyTable] FOREIGN KEY(ListingKey)
REFERENCES dbo.MyTable (ListingKey)
END
Execute the following query to search any constraint:
use MyDatabase
select c.name as c_name, t.name as t_name
from sys.key_constraints c
join sys.tables t on t.object_id = c.parent_object_id
If any constraint found on your table, remove it.
If you are receiving this error and you need to truncate the table then alternative solution could be that you can drop and re-create the table along with primary/other_keys/indexes/triggers. Please make sure that you don't need to the data in that table.
This soulution is working like a charm for me and hardly took a minute to finish. I am doing it for masking purpose.
Not for SQL Server but MySQL only.
Instead of deleting or recreating the constraint, I prefer this simpler way.
Disable the constraint validation by executing the following query first :
SET FOREIGN_KEY_CHECKS=0;
Then truncate your tables
And finally, reactivate the constraint validation :
SET FOREIGN_KEY_CHECKS=1;
Thats a common solution when you migrate databases, so you don't have to worry about the order the tables are inserted in.
I've already got a MySQL database therefore I wish to create mapping meta data from the existing database.
php app/console doctrine:mapping:convert xml ./src/MainBundle/Resources/config/doctrine/metadata/orm --from-database --force
However I got the following exception
[Doctrine\ORM\Mapping\MappingException]
Property "customerid" in "Accountcustomer" was already declared, but it must be declared only once
I haven't used customerId in any primary / composite key anywhere else in the database however I've used it as a foreign key several times.
However I do not know how having customerId in a composite key or another primary key could affect this.
Unfortunately Doctrine 2.0 does not support primary keys as foreign keys...
Check the link: http://www.doctrine-project.org/docs/orm/2.0/en/reference/limitations-and-known-issues.html
Another solution:
Drop all the foreign keys, Then it will work :) .
i know it is not recommended but it helped me. and generated Entities were working fine.
To drop all the foreign keys:
run this sql query -
MySQL
SELECT concat('ALTER TABLE ', TABLE_NAME, ' DROP FOREIGN KEY ', CONSTRAINT_NAME, ';')
FROM information_schema.key_column_usage
WHERE CONSTRAINT_SCHEMA = 'db_name' AND referenced_table_name IS NOT NULL;
PostgreSQL
SELECT concat('ALTER TABLE ', table_name, ' DROP CONSTRAINT IF EXISTS ', constraint_name, ';')
FROM information_schema.key_column_usage
WHERE constraint_schema = 'public' AND constraint_catalog = 'one' AND constraint_name LIKE '%_fkey';
and then run the resulted sql query again.
i got same error.
i generate entity from exists database.
php bin/console doctrine:mapping:import App\\Entity annotation --path=src/Entity --force --verbose --no-interaction
error message is 'Property "vacancy" in "User" was already declared, but it must be declared'
I found the cause of the error when debugging the doctrine
if there is relation between one table and more than one table with manytomany
and Column name is same on relate table
there is relation User table and vacancy_a,vacancy_b on vacancy_id column name.
select C.COLUMN_NAME,C.TABLE_NAME,K.* from information_schema.KEY_COLUMN_USAGE K inner join information_schema.`COLUMNS` C on (C.TABLE_NAME = K.TABLE_NAME and C.TABLE_SCHEMA = K.TABLE_SCHEMA) where K.TABLE_SCHEMA='schema_name' and K.REFERENCED_TABLE_NAME='**user**' and C.COLUMN_NAME='**vacancy**_id' order by C.COLUMN_NAME
Result of Query is relate column and table.
Solution : Rename to column name
ALTER TABLE vacancy_a CHANGE vacany_id vacancy_a_id int(11);
I got the same error and i noticed i had some double key (constraint) for single relationships in the db. Removing it, everythings worked fine.
Is there a way to change the value of a primary key which is referenced by another table as foreign key?
An easier alternative is to insert a new row and delete the old one. (Update any referencing rows in other tables before you do the delete)
There isn't an in-built UPDATE CASCADE if that's what you're after. You'd need to do something like disable any FK constraints; run UPDATE statements; re-enable the constraints.
Note that updating Primary Keys is (usually always) a bad idea.
You will need to disable the foreign key constraints before changing the primary key values, and then re-enable them afterwards.
If you actually want to implement "update cascade" functionality instead then see Tom Kyte's Update Cascade package
It is possible even without disabling constraints, in case if you would like only to swap keys (which is also a change's subset, so it might be still answer to your question). I wrote an example here: https://stackoverflow.com/a/26584576/1900739
update MY_TABLE t1
set t1.MY_KEY = (case t1.MY_KEY = 100 then 101 else 100 end)
where t1.MYKEY in (100, 101)
Yes, there is a way to do the cascading update in Oracle, even within a transaction (which does not hold true for the option of enabling/disabling constraints). However, you'll have to implement it yourself. It can be done via before/after-row-update triggers.
It is possible due to the fact that triggers are executed before any constraints are checked. (Well, at least in Oracle 11.2 it was true. Haven't checked against 12.1, but I honestly believe it hasn't changed.)
Anyway, as said before, updating primary keys is usually a bad idea.
The principe is to disable constrainsts, run your udates based on key, and reenable the constrainst. That for here is a script that run the disable script :
(Assuming all the constraints are enable at start)
Generate the script
SELECT 'alter table ' || uc.table_name|| ' disable constraint '|| uc.constraint_name|| ' ;'
FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'
Copy/paste the generated script and run it
alter table MYTABLE1 disable constraint FK_MYTABLE1 ;
alter table MYTABLE2 disable constraint MYTABLE2 ;
alter table MYTABLE3 disable constraint FK3_MYTABLE3 ;
...
Then update your PK values :
update MYTABLE1 set MYFIELD= 'foo' where MYFIELD='bar';
update MYTABLE2 set MYFIELD= 'foo' where MYFIELD='bar';
update MYTABLE3 set MYFIELD= 'foo' where MYFIELD='bar';
commit;
Generate the enable constraints script :
SELECT 'alter table ' || uc.table_name|| ' enable constraint '|| uc.constraint_name|| ' ;'
FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'
Another way you can do this is by changing the foreign key constraints so that the validation of the constraint is deferred until you commit - i.e. instead of Oracle validating the constraints statement-by-statement, it'll do it transaction-by-transaction.
Note you can't do this via the "alter table" statement, but you can drop and re-create the foreign key constraint to be deferrable, i.e:
alter table <table name> drop constraint <FK constraint name>;
alter table <table name> add constraint <FK constraint name> foreign key .... initially deferrable;
Once you've done that, just update the tables in whatever order you like, and commit - at which point, either:
All your FK constraints are satisfied, and everyone's happy; or
You've violated a FK constraint somewhere - you'll get an error and you'll have to fix up the data and commit, or rollback.
Note this feature is quite safe, as Oracle does not allow dirty reads so they'll only see the effects of your updates once you commit. So from the perspective of every other session, referential integrity appears to be preserved.
Also, this is a once-off change, so you don't need to go executing DDL each time you want to go updating the primary keys.
On table "A" depend about 30 other tables via FK to "A.Id".
For integration testing I have to drop the table and recreate it to create a defined state. Because of the dependent objects their seem to be no way to delete and recreate the table. The error message is:
Could not drop object 'dbo.A'
because it is referenced by a FOREIGN
KEY constraint
Question(s):
How can I drop and recreate table "A"?
(or) is there any way turn the schema dependencies off globally?
(or) is there any way to backup (all!) dependencies before deleting and restoring table "A" and restore all dependencies afterward?
Explore the sys.foreign_key_columns system table. Here's an example that I had laying around that will, given a table, tells you which of it's columns are keyed to another table:
DECLARE #tableName VARCHAR(255)
SET #tableName = 'YourTableName'
SELECT OBJECT_NAME(fkc.constraint_object_id) AS 'FKName', OBJECT_NAME(fkc.[referenced_object_id]) AS 'FKTable', c2.[name] AS 'FKTableColumn', #tableName AS 'Table', c1.[name] AS 'TableColumn'
FROM sys.foreign_key_columns as fkc
JOIN sys.columns AS c1 ON c1.[object_id] = fkc.[parent_object_id] AND c1.[column_id] = fkc.[parent_column_id]
JOIN sys.columns AS c2 ON c2.[object_id] = fkc.[referenced_object_id] AND c2.[column_id] = fkc.[referenced_column_id]
WHERE fkc.[parent_object_id] = OBJECT_ID(#tableName)
ORDER BY OBJECT_NAME(fkc.constraint_object_id)
With this, or some variation there-of, you could find out the foreign keys, drop them, do your stuff, and then re-create the foreign keys.
I should add that I know this works on SQL2005 and SQL2008. I don't really know if it will work on SQL2000/MSDE.
In Management Studio, you can right-click on the table and script the CREATE and the DROP which will include all of the foreign keys.
To be more specific, this will give you all constraints on which your Table depends. However, it does not give you the list of foreign keys that depend on this table. So, in addition to the scripts you would generate by right-clicking on the table in SMS, you need to find and script all the foreign keys. To get a list of them, you can run a query like so:
select FKConstraint.TABLE_NAME, FKConstraint.CONSTRAINT_NAME
from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As UniqueConstraint
On UniqueConstraint.CONSTRAINT_NAME = INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.UNIQUE_CONSTRAINT_NAME
Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As FKConstraint
On FKConstraint.CONSTRAINT_NAME = INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.CONSTRAINT_NAME
Where UniqueConstraint.TABLE_NAME = 'TableA'
For each one of these, you'll need to script the create and drop. You would append the drops to the top of your drop script and the creates at the end of your create script.
Go to the database in SSMS and right click. Choose tasks, generate scripts. Then go through the options and set them the way you want (Probaly to only choose foreign keys inthe table and create dependant objects and drop and recreate, dont;hve the options in front of me but you will see them. THen choose the tables you want to script the FKs for and script them to a file. Open the file and separate the drop statements into one file and the create statments into another. Now you have tweo files you can run do autmatically do what you want when ever you run run a test. I would suggest recreating the files before running the first test (in case they have changed since the last time tests were run) but not for each individual test.
Expand the table in Sql Server Management Studio, Expand the Constraints folder.
Write down any constraints that you have so you can re-create them. Delete the constraints and drop the table. Rebuild the table and re-create your constraints.
Use transaction.
At the end of test - rollback it.
Perhaps consider maintaining a virtual server with your database in its initialize test setup. Boot the VM, perform your testing, then throw away the changed VM.