I know that new feature of core data is unique constraints so I decide to test it. I created simple schema and when I add constraint for one field (firstName for example) - all works. If I add constraint for another field (lastName) - core data creates two different constraints for each field individually (I tried add two fields comma separated in one line and each field in separate line - no difference). But I want unique constraint for combination firstName + lastName, is it possible?
Thank you for reply!
It is possible to set uniqueness constraints for a combination of attributes. You were on the right path putting both attributes on the same line in the constraints:
You may have found this had no effect due to a problem with Xcode: the constraints are not actually updated in the model unless you modify some other aspect of the model at the same time (eg. change an attribute type and then change it back).
If you look at the SQL being generated, the table is created with a constraint:
CREATE TABLE ZSTOREOBJECT ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ...., CONSTRAINT ZLASTNAME_ZFIRSTNAME UNIQUE (ZLASTNAME, ZFIRSTNAME))
and when you insert new insert new values which fail this constraint (when the context is saved):
CoreData: sql: COMMIT
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: INSERT INTO ZSTOREOBJECT(Z_PK, Z_ENT, Z_OPT) VALUES(?, ?, ?)
CoreData: sql: UPDATE ZSTOREOBJECT SET ZLASTNAME = ?, ZFIRSTNAME = ? WHERE Z_PK = ?
CoreData: sql: ROLLBACK
and the error returned is:
Error Domain=NSCocoaErrorDomain Code=133021 "(null)" UserInfo={conflictList=(
"NSConstraintConflict (0x7fbd18d33c10) for constraint (\n lastName,\n firstName\n): ....
(This works in Xcode 7.2.1, with the iOS9.2 simulator; I haven't checked prior versions).
It seems that Xcode's typical behavior of persisting changes to disk on Run doesn't apply when setting constraints in the model editor. (Xcode 7.3, in my case.) 😞
Solution? Pretend it's 1990 all over again and hit ⌘-S after you change the constraints.
Related
I have an old application I am supporting that uses a Microsoft Access database. The original table design did not add primary keys to every table. I am working on a migration program that among other things is adding and filling in a new primary key field (GUID) when needed.
This is happening in three steps:
Add a new guid field with no constraints
Fill the field with new unique guids
Add the primary key constraints
My problem is setting the unique guids when the table has duplicate rows. Here is my code to set the guids.
Query.SQL.Add('SELECT * FROM ' + TableName);
Query.Open;
while Query.Eof = false do
begin
Query.Edit;
Query.FieldByName(NewPrimaryKeyFieldName).AsGuid := TGuid.NewGuid;
Query.Post;
Query.Next;
end;
FireDac generates an update statement that contains a where clause with all the original fields/values in the row (since there is no unique field for it to use). However, because the rows are complete duplicates the statement still updates two rows.
FireDac correctly errors with this message
Update command updated [2] instead of [1] record.
I can open up the database in Access and delete the duplicate records or assign them a unique guid by editing the table. I would like my conversion tool to automatically do this.
Is there some way to work with these duplicate rows in FireDac? Either to update just one at a time, or to delete just one of them?
In my opinion there is no way to do it with just one SQL Statement.
I would do this:
1. Copy the whole table without duplicates by using a new temp table
SELECT DISTINCT * FROM <TABLENAME>
Add the Keys
Delete old table content and copy new content from new table
Notes:
The DB Should be unavailable for everyone else for that Operation
2. Make BACKUP before
I am working with PostgreSQL database. I have created the required tables. Now I have to alter table columns as per constraints. I have to apply default constraint to one of my columns whose default value should be 1.
This is the query I am using,
ALTER TABLE Alerts ADD CONSTRAINT DF_Alerts_bIsActive SET DEFAULT ((1)) FOR bIsActive;
This is the error I am Getting,
ERROR: syntax error at or near "SET"
LINE 30: ... TABLE Alerts ADD CONSTRAINT DF_Alerts_bIsActive SET DEFAUL...
^
SQL state: 42601
Character: 948
Please can anyone suggest me the proper way to achieve this.
There is no such thing as a "default constraint". You simply define default values.
alter table alerts alter column bisactive set default 1;
Unrelated, but:
bisactive sounds like that is some kind of flag. You should define that as a proper boolean column, not an integer.
I am using Entity Framework 6.1.3 and a database first approach.
It is a small database with a many to many relationship between Tags and BoxedItems, a table named ItemsTags holds the relationship.
I get an exception when using the scaffolded code to delete a BoxedItem:
db.BoxedItems.Remove(boxedItem);
db.SaveChanges();
SqlException: The DELETE statement conflicted with the REFERENCE
constraint "FK_ItemsTags_Items". The conflict occurred in database
"TimeBox", table "dbo.ItemsTags", column 'IdItem'.
The relationship table code is bellow. The PK for BoxedItem needs to be a Guid and for Tags is a INT IDENTITY (1, 1).
CREATE TABLE [dbo].[ItemsTags] (
[IdItem] UNIQUEIDENTIFIER NOT NULL,
[IdTag] INT NOT NULL,
CONSTRAINT [PK_ItemsTags] PRIMARY KEY CLUSTERED ([IdItem] ASC, [IdTag] ASC),
CONSTRAINT [FK_ItemsTags_Tags] FOREIGN KEY ([IdTag]) REFERENCES [dbo].[Tags] ([Id]),
CONSTRAINT [FK_ItemsTags_Items] FOREIGN KEY ([IdItem]) REFERENCES [dbo].[BoxedItems] ([Id])
);
Would the EF auto generated code work out of the box if my BoxedItem PK was INT IDENTITY (1, 1)? EF seems to like it more for auto generated code.
Is there a smarter way to delete the BoxedItem, other than a custom SQL instruction?
In my iOS app,I want to change the column data type in database.
ALTER TABLE XXX ALTER COLUMN myColumn INT.
I always get 'near ALTER Syntax error'
How to resolve the problem?
Thanks for your help.
You cannot change the column type. You can create a new table, using the correct data type for the column this time, and then select data from the old table and insert it into the new table. The full procedure is outlined in the ALTER TABLE documentation:
Remember the format of all indexes and triggers associated with table X. This information will be needed in step 7 below. One way to do this is to run a query like the following: SELECT type, sql FROM sqlite_master WHERE tbl_name='X'.
Use CREATE TABLE to construct a new table "new_X" that is in the desired revised format of table X. Make sure that the name "new_X" does not collide with any existing table name, of course.
Transfer content from X into new_X using a statement like: INSERT INTO new_X SELECT ... FROM X.
If foreign key constraints are enabled, disable them using PRAGMA foreign_keys=OFF.
Drop the old table X: DROP TABLE X.
Change the name of new_X to X using: ALTER TABLE new_X RENAME TO X.
Use CREATE INDEX and CREATE TRIGGER to reconstruct indexes and triggers associated with table X. Perhaps use the old format of the triggers and indexes saved from step 1 above as a guide, making changes as appropriate for the alteration.
If foreign key constraints were originally enabled (prior to step 4) then run PRAGMA foreign_key_check to verify that the schema change did not break any foreign key constraints, and run PRAGMA foreign_keys=ON to re-enable foreign key constraints.
If any views refer to table X in a way that is affected by the schema change, then drop those views using DROP VIEW and recreate them with whatever changes are necessary to accommodate the schema change using CREATE VIEW.
Note, SQLite uses type affinity (the column definition doesn't alter what type of data you insert into the table). So if you change the data type, you'll want to change the data, too.
ALTER TABLE table ADD newColumn INTEGER;
UPDATE table SET newColumn = oldColumn;
Continuing to the post of reading-from-XML-and-storing-the-values-in-database-using-grails
am facing an another problem in it. As the employee id is related to other tables as foreign key how am suppose to insert the data into the database without conflict what i want to add in grails code to avoid the below displayed error.
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Cannot
add or update a child rowL a foreign key constraint fails.. ( CONSTRAINT 'EMPLOYEE_ID_HEADER'
FOREIGN KEY ('EMPLOYEE_ID') REFERENCES 'employee_header'('employee_id'))
here employee_id is a column and employee_header is a separate table that contains employee_id as a foreign key.
Finally I got the answer, when you are inserting the values in database the related foreign key tables will get affects initially. So to handle this situation we have to insert the foreign key related table at first then the table we need to add exactly.
For the reference, at first I had given the code like this
sql.executeInsert("insert into order_item (order_id,product_id,
order_item_seq_id) values (${order_id},${product_id},${order_item_seq_id})")
sql.executeInsert("insert into product(product_id) values(${product_id})")
This first inserts the order_item table then the foreignkey constraint table product, so the data did not inserted. So the correct code is
sql.executeInsert("insert into order_header(order_id) values(${order_id})")
sql.executeInsert("insert into product(product_id) values(${product_id})")
sql.executeInsert("insert into order_item (order_id,product_id,
order_item_seq_id) values (${order_id},${product_id},${order_item_seq_id})")
Now this inserts the data successfully without errors.