I have two tables:
TableA
TableB
I have a constraint and relation between my tables.
I modify something on my TableA or TableB (for example: change datatype, or add a new column). Should I drop and create the constraint again?
Definitely you don't need to recreate a constraint for new columns.
For datatypes, it depends whether the alteration is on a contrainted column or not. If it is constrainted column, you first need to drop constraint then make alteration and create the constraint again.
Most RDBMS systems do not allow alteration of datatypes on constrainted columns.
Related
I need to create a table having a field, which is a foreign key referencing to another query rather than existing table. E.g. the following statement is correct:
CREATE TABLE T1 (ID1 varchar(255) references Types)
but this one throws a syntax error:
CREATE TABLE T2 (ID2 varchar(255) references SELECT ID FROM BaseTypes UNION SELECT ID FROM Types)
I cannot figure out how I can achieve my goal. In the case it’s needed to introduce a temporary table, how can I force this table being updated each time when tables BaseTypes and Types are changed?
I am using Firebird DB and IBExpert management tool.
A foreign key constraint (references) can only reference a table (or more specifically columns in the primary or unique key of a table). You can't use it to reference a select.
If you want to do that, you need to use a CHECK constraint, but that constraint would only be checked on insert and updates: it wouldn't prevent other changes (eg to the tables in your select) from making the constraint invalid while the data is at rest. This means that at insert time the value could meet the constraint, but the constraint could - unnoticed! - become invalid. You would only notice this when updating the row.
An example of the CHECK-constraint could be:
CREATE TABLE T2 (
ID2 varchar(255) check (exists(
SELECT ID FROM BaseTypes WHERE BaseTypes.ID = ID2
UNION
SELECT ID FROM Types WHERE Types.ID = ID2))
)
For a working example, see this fiddle.
Alternatively, if your goal is to 'unite' two tables, define a 'super'-table that contains the primary keys of both tables, and reference that table from the foreign key constraint. You could populate and update (eg insert and delete) this table using triggers. Or you could use a single table, and replace the existing views with an updatable view (if this is possible depends on the exact data, eg IDs shouldn't overlap).
This is more complex, but would give you the benefit that the foreign key is also enforced 'at rest'.
Noob to SQL here. Is there any way to constrain (not in terms of primary/foreign key) the selection of a column? Specifically, I want to a table called “occupation” with only two options, either clown or doctor.
There are two methods. The simplest is a check constraint:
alter table t
add constraint chk_t_occupation
check (occupation in ('clown', 'doctor'));
The second method is to have an occupations table with two rows. You can then have an occupationId column with a foreign key reference to this table.
I have a FK inside my table but i want to modify the parent table for the FK . so is there an alter command that can achieve this ? or i need to remove the FK and create a new one ?
Thanks
Add this to your PK and it will automatically update all FKs for you:
ON UPDATE CASCADE
For full details, you can read this article.
EDIT Based on your comment, if you want to change the PK data type, it depends on the change:
If the old type can be implicitly casted to the new type without any loss:
Change the PK type first.
Change the FK type to the same.
If the old type cannot be implicitly casted to the new type without any loss:
Break the relationship first (i.e. remove the FK restriction/index).
Convert the PK. If the data needs to be modified, save both the old values and the new ones in a temporary table.
Convert the FK. If the PK data was changed in previous step, update the FK using the mapped values from the temporary table.
Create the relationship again (i.e. create the FK restriction/index).
To modify the data type, use the ALTER command, the syntax is:
ALTER TABLE table_name
ALTER COLUMN column_name datatype
Examples:
ALTER TABLE table_name
ALTER COLUMN id NUMBER(10,2);
ALTER TABLE table_name
ALTER COLUMN id VARCHAR(20);
For full details, you can read this article.
Looks like you are looking for alter statement but since you didn't mention exactly what you are looking to modify; I assume that you want to change column data type size. You can do something like this (an example; say you want to change size from 10 to 15)
alter table sample3
alter column name varchar(15)
EDIT:
In that case this is what you should be doing. You need to drop the existing constraint and recreate the constraint to point to TableC
alter table TableA
drop constraint your_FK_constraint_name
alter table TableA
add constraint constraint_name
FOREIGN KEY (column_name) references TableC(some other column name)
An Example:
alter table sample2
drop constraint FK__sample2__realnam__09DE7BCC
alter table sample2
add constraint FK__sample2__realnam
FOREIGN KEY (realname) references sample1(name)
Based on this comment, "now my current FK inside TableA is referring to another table primary key TableB. but i need my modify my current FK to refer to tableC instead of tableB ... this what i need (to modify the parent table for my FK)– "
The parent table is TableB. No action is required on that table.
On TableA, you have to:
Drop the existing foreign key constraint.
Update as necessary so that all values in the applicable column have a matching value in TableC.
Add a new foreign key constraint.
in that order.
Edit Starts Here
Here is a link to the syntax,
I have written the following constraint for a column I've called 'grade':
CONSTRAINT gradeRule CHECK grade IN (‘easy’, ‘moderate’, ‘difficult’),
Is it possible to later update the gradeRule to have different values? For example, 'moderate' and 'difficult' could be changed to 'medium' and 'hard'.
Thanks
You could drop the existing constraint, and add the new constraint with the NOCHECK option. This would allow you to add the constraint even though data in the table violates the constraint. The problem with doing this though would be that you wouldn't be able to update existing records without making them pass the constraint first.
ALTER TABLE SomeTable DROP CONSTRAINT gradeRule
GO
ALTER TABLE SomeTable ADD CONSTRAINT gradeRule ... WITH NOCHECK
GO
Although this is possible, its not usually recommended because of the potential problems with future updates of the data.
Drop the constraint, and then add the replacement constraint.
You can't update a constraint in SQL Server at least.
ALTER TABLE SomeTable DROP CONSTRAINT gradeRule
In addition, you'll need to update the table data before adding the new constraint, so that it meets the new constraint.
If you change the constraint, all of the data currently in the table must meet the constraint. So if you had 2 rows of data with 'moderate' and tried to change the constraint to easy, medium, and hard, it would not let you.
So you would have to make the new constraint (easy, moderate, medium, difficult, hard) or, update the data to the new values - moderate --> medium etc.
I have a bunch of tables using user-defined data type for PK column. Is it possible to change this type Using SQL Server 2005?
I would suggest that it is always possible to refactor poor or outmoded database designs, it simply depends on how much work you are willing to go to in order to do so.
If you are looking to replace the user-defined data with a surrogate key then you should be able to simply alter the existing table to contain a non-nullable identity column and this should cause all of the existing records to be assigned a new key automatically.
Once the new field is populated with unique id's, if you need to move out and replace foreign key references to this table, then I would simply alter those tables to contain the new field and use something like the following:
UPDATE child_table
SET new_fk_val =
SELECT new_pk_val
FROM parent_table
WHERE parent_table.old_pk_val = child_table.old_fk_val
Once that step is complete, then you could drop the old foreign key constraint, drop the old foreign key column, drop the old primary key column, establish the new primary key constraint, and then establish the new foreign key constraint.
Of course, if the old version of the parent and child tables relationship was such that you have invalid records in the child table you may have to do something like the following:
DELETE FROM child_table
WHERE old_fk_val NOT IN
( SELECT old_pk_val FROM parent_table)