changing the primary key value in SQL server 2005 - database

I have a Table which has a Primary Key field which is not set to auto-increment.
I want to change one of these primary keys to something different.
The problem arises with the other tables relations. The thing is, the guy who built this system did not build relations in SQL Server, but rather manually coded some override in the program that uses it - a VB 6 program.
How would I update a Primary Key and all instances of the Primary Key in other databases? I have to manually look for the instances(although I do know they are in only two tables) of the Primary Key and change them, but how do I do that?

Even though the person who first created the tables didn't include foreign keys to them, you can add them now if foreign keys are honored in your tables. When you create the foreign keys, create them with ON UPDATE CASCADE option. This way, when you update your primary key, the related foreign keys will also be updated.

One thing I would suggest is using the query of:
select * from INFORMATION_SCHEMA.Columns where Column_Name = 'FieldID'
This queries the metadata to see all where that field exists, just in case there are more. Then, just write an update script to change the key, unfortunately its a manual process but being that the relationship is missing it will make scripting easier.

Related

Update table primary key and propagate changes to other tables

I have Table A with Column A1Id as primary key, Column A1 and Column A2.
I have Table B with Column A1Id as foreign key, Column B1, and Column B2.
I have Table C with Column AI1d as foreign key, Column C1, and Column C2.
How can i update all the columns with a single command?
How can i propagate changes to all foreign keys if i update the primary key?
I'm new to SQL is this a trivial task?
I'm currently having difficulty updating a single table because of the foreign key constraint.
How can i update all the columns with a single command?
How can i propagate changes to all foreign keys if i update the primary key?
is this a trivial task?
You can't do this with a single command, it is not a trivial task, it typically takes a script of sql commands with the changes repeated for each table; usually involving UPDATEs and new columns to "migrate" the old data to the new format. Changing primary keys is something that is done very infrequently, and is almost always considered a major change even when the specifics of that change are fairly minor.
The closest (physical) analogy I can think of offhand is trying to take something apart and replace all it's screws with bolts.
Edit: If you are just talking about changing the values, not the fields or data type of the values, used as primary keys; then R VISHAL's answer is pointing in the right direction. You'll need to drop all your current constraints and recreate them to cascade the updates. You can also disable foreign key checks, change the values and then re-enable foreign key checks; but that is generally not recommended as re-enabling them does not recheck them, so if your updates put the data in an inconsistent state, it will not be corrected or even detected; and the setting is global, so any other activity going on will also be free to ignore their own fk constraints.
... but you shouldn't typically be changing primary key values either. If the value changes, it probably isn't a good candidate for a foreign key; and if it is a synthetic value (like an auto-incremented id) then you should almost never be changing it (many newer users are tempted to try to "condense" them when holes appear, but it is seldom a good idea.)
If, in your case, table B(A1id) and table C(A1id) both reference table A(A1id), then to propagate either update or delete operations to all foreign keys of tables B,C they should have the CASCADE constraint in them. In MySQL, for example, you could do this:
ALTER TABLE B
ADD CONSTRAINT FKA
FOREIGN KEY B(A1id)
REFERENCES A(A1id)
ON UPDATE CASCADE
ON DELETE CASCADE
Notice the word cascade. Is this what u want or am I missing something here? :/

Dropping and recreating unexpected primary keys

I have a tool which uses SQL scripts to apply changes to a customer database. Often this invloves changing a column definition (datatype etc). The problem is that often there are primary keys applied by the user that we don't know about (and they don't remember), which trips up the process (eg when changing columns belonging to the indexes or primary keys).
The requirement given to me is that this update process should be 'seamless', with no human involvement to prepare the ground. I have also researched this on this forum, and as far as I can see my particular question has not yet been asked.
I know how to disable and then later rebuild all indexes on a database, and even those only in certain tables, but if the index is on a primary key I still can't change any column that is part of the primary key unless I explicitly drop the PK by name, and later recreate it explicitly, which means I have to know about it at code-time. I can probably write a query to find the name of the primary key on a table if one is there, but how to know how to recreate it?
How can I, using Transact-SQL (or PL/SQL), detect, drop and then recreate the primary keys on given tables, without knowing at code time what they are or what columns belong to them? The key is that the tool cannot know in advance what the primary keys are are on any given table, nor what they comprise. The SQL code must handle this itself.
Better still would be to detect if a known column belongs to a primary key, then drop and later recreate that after I have changed the column.
This needs to be done in both Oracle and Sql Server, ideally purely with SQL code.
TIA
I really don't understand why would a customer define his own primary keys for the tables? Moreover, I don't understand why would you let them? In my world, if customer changes schema in any way, this automatically means end of support for them.
I will strongly advise against dropping and recreating primary keys on production database. Any number of bad things can happen, leading to data loss.
And it's not just the PKs, you will have to drop the foreign key constraints first. And FKs may reference not only the PKs but the unique constraints as well, so yao have to deal with those as well.
Your best bet would be to create a new table with the required schema, copy the data, drop original table and rename the new one. Of course, you will have to handle the FKs, but it's easier. Check this link an example:
http://sqlblog.com/blogs/john_paul_cook/archive/2009/09/17/script-to-create-all-foreign-keys.aspx

Can't work around this foreign key constraint rule using TRIGGER in SQLite?

First, I want to talk a little about the Foreign key constraint rule and how helpful it is. Suppose I have two tables, a primary table with the primary column called ID, the other table is the foreign one which also has a primary column called ID. This column in the foreign table refers to the ID column in the primary table. If we don't establish any Foreign key relation/constraint between those tables, we may fall foul of many problems related to integrity.
If we create the foreign key relation for them, any changes to the ID column in primary table will 'auto' reflect to the ID column in the foreign table, changes here can be made by DELETE, UPDATE queries. Moreover, any changes to the ID in the foreign table should be constrained by the ID column in the primary table, for example there shouldn't any new value inserted or updated in the ID column of the foreign table unless it does exist in the ID column of the primary table.
I know that SQLite doesn't support foreign key constraint (with full functions as detailed above) and I have to use TRIGGER to work around this problem. I have used TRIGGER to work around successfully in one way (Any changes to the ID column in the primary table will refect to the ID column in the foreign table) but the reverse way (should throw/raise any error if there is a confict occurs, for example, there are only values 1,2,3 in the ID column of the primary table, but the value 2 in the ID column of the foreign table is updated to 4 -> not exist in the primary table -> should throw error) is not easy. The difficult is SQLite doesn't also support IF statement and RAISERROR function. If these features were supported, I could work around easily.
I wonder how you can use SQLite if it doesn't support some important features? Even working around by using TRIGGER is not easy and I think it's impossible, except that you don't care about the reverse way. (In fact, the reverse way is not really necessary if you set up your SQL queries carefully, but who can make sure? Raising error is a mechanism reminding us to fix and correct and making it work exactly without corrupting data and the bugs can't be invisible.
If you still don't know what I want, I would like to have some last words, my purpose is to achieve the full functionality of the Foreign key constraint which is not supported in SQLite (even you can create such a relationship but it's fake, not real as you can benefit from it in SQL Server, SQL Server Ce, MS Access or MySQL).
Your help would be highly appreciated.
PS: I really like SQLite because it is file-based, easy to deploy, supports large file size (an advantage over SQL Server Ce) but some missing features have made me re-think many times, I'm afraid if going for it, my application may be unreliable and corrupt unpredictably.
To answer the question that you have skillfully hidden in your rant:
SQLite allows the RAISE function inside triggers; because of the lack of control flow statements, this must be used with a SELECT:
CREATE TRIGGER check_that_id_exists_in_parent
BEFORE UPDATE OF id ON child_table
FOR EACH ROW
BEGIN
SELECT RAISE(ABORT, 'parent ID does not exist')
WHERE NOT EXISTS (SELECT 1
FROM parent_table
WHERE id = NEW.id);
END;

Should GUID be used as a foreign key to many tables

I designed a database to use GUIDs for the UserID but I added UserId as a foreign key to many other tables, and as I plan to have a very large number of database inputs I must design this well.
I also use ASP Membership tables (not profiles only membership, users and roles).
So currently I use a GUID as PK and as FK in every other table, this is maybe bad design?
What I think is maybe better and is the source of my question, should I add in Users table UserId(int) as a primary key and use this field as a foreign key to other tables and user GUID UserId only to reference aspnet_membership?
aspnet_membership{UserID(uniqueIdentifier)}
Users{
UserID_FK(uniqueIdentifier) // FK to aspnet_membership table
UserID(int) // primary key in this table --> Should I add this
...
}
In other tables user can create items in tables and I always must add UserId for example:
TableA{TableA_PK(int)..., CreatedBy(uniqueIdentifier)}
TableB{TableB_PK(int)..., CreatedBy(uniqueIdentifier)}
TableC{TableC_PK(int)..., CreatedBy(uniqueIdentifier)}
...
Ultimately the answer is that it really depends.
Microsoft have documented the performance differences of each here. While the article differs slightly to your situation, as you have to use a UNIQUEIDENTIFIER to link back to asp membership, many of the discussion points still apply.
If you have to create your own users table anyway it would make more sense to have your own int primary key, and use the GUID as a foreign key. It keeps separate entities separate. What if at some point in the future you wanted to add a different membership to a user? You would then need to update a primary key, which would have to cascade to any tables referencing this and could be quite a performance hit. If it is just a unique column in your users table it is a simple update.
All binary datatypes (uniqueidetifier is binary(16)) are fine as foreign keys. But GUID might cause another small problem as primary key. By default primary key is clustered, but GUID is generated randomly not sequentially as IDENTITY, so it will frequently split IO pages, that cause performance degradation a little.
I'd go ahead with your current design.
If you're worried because of inner joins performance in your queries because of comparing strings instead of ints, nowadays there is no difference at all.

How can we make foreign key among tables after inserting data in those tables?

I have created tables in sql server. And i have also inserted data/rows in that tables.
Now i want to make relationship among them means i want to create foreign key constraints among them, is it possible ?
Whenever i try to create relationship among table a problem is occured. "Saving changes is permitted, The changes you made required table to re-created and dropped"
Please suggest me what should i do to make relationship(foreign key) among them ?
My Child table design is this
this is my parent table:-
please now right what alter query i should write..?
You can try this link
"Error message when you try to save a table in SQL Server 2008: "Saving changes is not permitted"
Another solution is below.
I think the problem is because of a feature when using the GUI. If you have a look at this link it shows you how to work round it. It is a feature which prevents you from dropping and recreating the table which is what SSMS does in the background when you click ok.
The code provided by the previous posted is the best way to do this.
You could do this with a script like this:
alter table ChildTable
add constraint FK_ChildTable_ColumnName foreign key (ColumnName) references ParentTable(PrimaryKeyColumnName)
[Edit] If I read your description correctly the script would be:
alter table emp
add constraint FK_emp_salary foreign key(salary) references testing(roll)
You can only add foreign constraints that aren't violated by existing data. You may also have to add suitable indices first, although this depends on the DBMS. In any case, first make sure your existing data is compatible with the foreign keys you want to introduce. In other words, if you were to create the foreign key first, and then insert the data, you should not produce any foreign key violations.

Resources