Altering multiple objects in in query - sql-server

The code below is attempting to alter 2 columns at once in a table. Can it be done and am I just doing it wrong?
Alter table verdata
Add Primary Key(Asset_ID)
Add foreign key(Asdes) References AssetDesc(AssetDescription)

To add constraints in alter query,
follow the below,
ALTER TABLE ADD CONSTRAINT adds a table-level constraint to an existing table. Any supported table-level constraint type can be added via ALTER TABLE. The following limitations exist on adding a constraint to an existing table:
When adding a foreign key or check constraint to an existing table, Derby checks the table to make sure existing rows satisfy the constraint. If any row is invalid, Derby throws a statement exception and the constraint is not added.
All columns included in a primary key must contain non null data and be unique.
ALTER TABLE ADD UNIQUE or PRIMARY KEY provide a shorthand method of defining a primary key composed of a single column. If PRIMARY KEY is specified in the definition of column C, the effect is the same as if the PRIMARY KEY(C) clause were specified as a separate clause. The column cannot contain null values, so the NOT NULL attribute must also be specified.
For information on the syntax of constraints, see CONSTRAINT clause. Use the syntax for table-level constraint when adding a constraint with the ADD TABLE ADD CONSTRAINT syntax.
REFERENCE

Related

How can I drop a constraint with multiple columns as the primary key in SQL Server?

My code looks like this:
CONSTRAINT user_password_username_password PRIMARY KEY (username, password)
I need to drop this constraint because I updated the foreign keys and no longer can use password in the constraint. I also cannot simply drop the table and recreate it because it is linked to other tables. How can I drop this constraint so only username will make up the primary key?
Drop all foreign key constraints referencing the user_password_username_password constraint. Disable will not work; you must drop them. You may need to drop foreign keys that reference other unique keys on the table, but I'm not sure about that.
Drop the user_password_username_password constraint on the table.
Create a new unique/primary key constraint on the table.
Create or recreate any foreign key constraints.
I believe you can do all this in a single transaction, but if it's a large table I'd consider doing this in single user mode. You'll be dropping a primary key which causes an index rebuild for every index and constraint on the table, then potentially creating several new indexes/constraints in the foreign keys, and then creating the new primary key which again forces all the indexes and constraints on the table to rebuild.

Adding a column as a foreign key gives ERROR column referenced in foreign key constraint does not exist

I have the following set up,
CREATE TABLE auth_user ( id int PRIMARY KEY );
CREATE TABLE links_chatpicmessage ();
I'm trying to add a column named sender to links_chatpicmessage which is a foreign key to another table called auth_user's id column.
To achieve the above, I'm trying the following on terminal:
ALTER TABLE links_chatpicmessage
ADD FOREIGN KEY (sender)
REFERENCES auth_user;
But this gives me an error:
ERROR: column "sender" referenced in foreign key constraint does not
exist
How do I fix this?
To add a constraint to a column It needs to exists first into the table there is no command in Postgresql that you can use that will add the column and add the constraint at the same time. It must be two separate commands. You can do it using following commands:
First do as:
ALTER TABLE links_chatpicmessage ADD COLUMN sender INTEGER;
I use integer as type here but it should be the same type of the id column of the auth_user table.
Then you add the constraint
ALTER TABLE links_chatpicmessage
ADD CONSTRAINT fk_someName
FOREIGN KEY (sender)
REFERENCES auth_user(column_referenced_name);
The ADD CONSTRAINT fk_someName part of this command is naming your constraint so if you latter on need to document it with some tool that create your model you will have a named constraint instead of a random name.
Also it serves to administrators purposes so A DBA know that constraint is from that table.
Usually we name it with some hint about where it came from to where it references on your case it would be fk_links_chatpicmessage_auth_user so anyone that sees this name will know exactly what this constraint is without do complex query on the INFORMATION_SCHEMA to find out.
EDIT
As mentioned by #btubbs's answer you can actually add a column with a constraint in one command. Like so:
alter table links_chatpicmessage
add column sender integer,
add constraint fk_test
foreign key (sender)
references auth_user (id);
You can do this in Postgres on one line:
ALTER TABLE links_chatpicmessage
ADD COLUMN sender INTEGER
REFERENCES auth_user (id);
You don't need to manually set a name. Postgres will automatically name this constraint "links_chatpicmessage_auth_user_id_fkey".
I know this answer is way late, and I realize this is the same as btubbs one-liner, just a little more descriptive ...
Assuming you want to reference the primary key in table auth_user and that key name is 'id'.
I use this syntax:
ALTER TABLE links_chatpicmessage
ADD COLUMN sender some_type,
ADD FOREIGN KEY (sender) REFERENCES auth_user(id);
Note: some_type = [type the same as sender in table auth_user]
The CONSTRAINT clause is optional. I suggest ommiting it and always letting PostgreSQL autoname the constraint, without naming it you'll get a logical name
"links_chatpicmessage_sender_fkey" FOREIGN KEY (sender) REFERENCES auth_user(id)
That's what you'll likely want to know if an INSERT or UPDATE fails due to a constraint violation.
Syntax to add a foreign key
All of these are somewhat documented on ALTER TABLE
To a new column
ALTER TABLE links_chatpicmessage
ADD COLUMN sender int,
ADD [CONSTRAINT foo] FOREIGN KEY (sender) REFERENCES auth_user(id);
This is compound and transactional. You can issue two ALTER statements on the same table by separating the two statements with a ,.
To a preexisting column
-- assumes someone has already added the column or that it already exists
ALTER TABLE links_chatpicmessage
ADD COLUMN sender int;
ALTER TABLE links_chatpicmessage
ADD [CONSTRAINT foo] FOREIGN KEY (sender) REFERENCES auth_user(id);
foreign key reference for existing column
ALTER TABLE table_name
ADD CONSTRAINT fkey_name
FOREIGN KEY (id)
REFERENCES ref_table(id)

Drop a Unique Constraint

I need to drop a Unique constraint on a previously existing table and create a new unique constraint that will include extra column. Can I use the name of the constraint to drop it? or will the name of the unique constraint change based on Datasource. I need to execute the script on multiple instances of same DB (eg. dev,test,prod)
Yes, you can use the name of the constraint, provided that you previously deleted and it was a named contraint.

How do I modify this SQL schema to constrain data in tables?

Newbie in need of help.
I'm creating a small database.
I want to constrain data in a couple of tables - Lender and Pingtree. The ProviderType table contains lookup data and contains either 'Lender' or 'Pingtree'. How can I modify this structure so that the Lender table only can contain Lender types and Pingtree, Pingtree types?
Guessing that ProviderTypeID is the column in the Provider table that distinguishes between the two types, then you must add this same column to both the Lender and Pingtree tables, add a suitable key (if it doesn't already exist) in Provider on ID, ProviderTypeId, and then add a composite FOREIGN KEY constraint to the Lender and Pingtree tables that include these columns.
While this may sound like a drag, it is a known pattern called supertyping/subtyping. When the supertype (Provider) can be multiple subtypes, you don't need the TypeId column. But when the subtypes are mutually exclusive, this is what you must do.
It might look something like this:
ALTER TABLE dbo.Lender ADD ProviderTypeId tinyint NOT NULL
CONSTRAINT DF_Lender_ProviderTypeID DEFAULT (1)
CONSTRAINT CK_Lender_ProviderTypeID_Is_Lender CHECK (ProviderTypeID = 1);
ALTER TABLE dbo.Pingtree ADD ProviderTypeId tinyint NOT NULL
CONSTRAINT DF_Pingtree_ProviderTypeID DEFAULT (2)
CONSTRAINT CK_Pingtree_ProviderTypeID_Is_Pingtree CHECK (ProviderTypeID = 2);
-- Any of a PK, UNIQUE constraint, or unique index will do
ALTER TABLE dbo.Provider ADD CONSTRAINT UQ_Provider_ID_ProviderTypeID
UNIQUE (ID, ProviderTypeID);
ALTER TABLE dbo.Lender DROP CONSTRAINT FK_Lender_ProviderId;
ALTER TABLE dbo.Lender ADD CONSTRAINT FK_Lender_ProviderId_ProviderTypeId
FOREIGN KEY (ID, ProviderTypeID) REFERENCES dbo.Provider (ID, ProviderTypeID);
ALTER TABLE dbo.PingTree DROP CONSTRAINT FK_PingTree_ProviderId;
ALTER TABLE dbo.PingTree ADD CONSTRAINT FK_PingTree_ProviderId_ProviderTypeId
FOREIGN KEY (ID, ProviderTypeID) REFERENCES dbo.Provider (ID, ProviderTypeID);
If written correctly (specifying the column list on INSERT) your stored procedures and application SQL code should not have to change.

Are foreign keys indexed automatically in SQL Server?

Would the following SQL statement automatically create an index on Table1.Table1Column, or must one be explicitly created?
Database engine is SQL Server 2000
CREATE TABLE [Table1] (
. . .
CONSTRAINT [FK_Table1_Table2] FOREIGN KEY
(
[Table1Column]
) REFERENCES [Table2] (
[Table2ID]
)
)
SQL Server will not automatically create an index on a foreign key. Also from MSDN:
A FOREIGN KEY constraint does not have
to be linked only to a PRIMARY KEY
constraint in another table; it can
also be defined to reference the
columns of a UNIQUE constraint in
another table. A FOREIGN KEY
constraint can contain null values;
however, if any column of a composite
FOREIGN KEY constraint contains null
values, verification of all values
that make up the FOREIGN KEY
constraint is skipped. To make sure
that all values of a composite FOREIGN
KEY constraint are verified, specify
NOT NULL on all the participating
columns.
As I read Mike's question, He is asking whether the FK Constraint will create an index on the FK column in the Table the FK is in (Table1). The answer is no, and generally. (for the purposes of the constraint), there is no need to do this The column(s) defined as the "TARGET" of the constraint, on the other hand, must be a unique index in the referenced table, either a Primary Key or an alternate key. (unique index) or the Create Constraint statment will fail.
(EDIT: Added to explicitly deal with comment below -)
Specifically, when providing the data consistency that a Foreign Key Constraint is there for. an index can affect performance of a DRI Constraint only for deletes of a Row or rows on the FK side. When using the constraint, during a insert or update the processor knows the FK value, and must check for the existence of a row in the referenced table on the PK Side. There is already an index there. When deleting a row on the PK side, it must verify that there are no rows on the FK side. An index can be marginally helpful in this case. But this is not a common scenario.
Other than that, in certain types of queries, however, where the query processor needs to find the records on the many side of a join which uses that foreign key column. join performance is increased when an index exists on that foreign key. But this condition is peculiar to the use of the FK column in a join query, not to existence of the foreign Key constraint... It doesn't matter whether the other side of the join is a PK or just some other arbitrary column. Also, if you need to filter, or order the results of a query based on that FK column, an index will help... Again, this has nothing to do with the Foreign Key constraint on that column.
No, creating a foreign key on a column does not automatically create an index on that column. Failing to index a foreign key column will cause a table scan in each of the following situations:
Each time a record is deleted from the referenced (parent) table.
Each time the two tables are joined on the foreign key.
Each time the FK column is updated.
In this example schema:
CREATE TABLE MasterOrder (
MasterOrderID INT PRIMARY KEY)
CREATE TABLE OrderDetail(
OrderDetailID INT,
MasterOrderID INT FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)
OrderDetail will be scanned each time a record is deleted in the MasterOrder table. The entire OrderDetail table will also be scanned each time you join OrderMaster and OrderDetail.
SELECT ..
FROM
MasterOrder ord
LEFT JOIN OrderDetail det
ON det.MasterOrderID = ord.MasterOrderID
WHERE ord.OrderMasterID = #OrderMasterID
In general not indexing a foreign key is much more the exception than the rule.
A case for not indexing a foreign key is where it would never be utilized. This would make the server's overhead of maintaining it unnecessary. Type tables may fall into this category from time to time, an example might be:
CREATE TABLE CarType (
CarTypeID INT PRIMARY KEY,
CarTypeName VARCHAR(25)
)
INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')
CREATE TABLE CarInventory (
CarInventoryID INT,
CarTypeID INT FOREIGN KEY REFERENCES CarType(CarTypeID)
)
Making the general assumption that the CarType.CarTypeID field is never going to be updated and deleting records would be almost never, the server overhead of maintaing an index on CarInventory.CarTypeID would be unnecessary if CarInventory was never searched by CarTypeID.
According to: https://learn.microsoft.com/en-us/sql/relational-databases/tables/primary-and-foreign-key-constraints?view=sql-server-ver16#indexes-on-foreign-key-constraints
Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index

Resources