63

UPDATE

Here are the constraints as a result of the query

SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 'history'

CONSTRAINT_NAME   COLUMN_NAME  ORDINAL_POSITION
PK_history        userKey       1
PK_history        name          2

Here is the result of the query

SELECT * 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
WHERE TABLE_NAME = 'history'

CONSTRAINT_NAME   CONSTRAINT_TYPE  IS_DEFERRABLE  INITIALLY_DEFERRED
PK_history        PRIMARY KEY      NO             NO

END UPDATE

My host provides an interface to my SQL Server DB via ASP.NET Enterprise Manager.

I have 3 columns in my history table:

  • userId (key, int, NULL not allowed)
  • name (key, string, NULL not allowed)
  • id (not key, int, NULL allowed)

I want to make the id column the only key.

To do that, I believe I need to:

  1. Make sure there are no NULLs in that column for any row
  2. Set the column to not allow NULLs
  3. Add the column as a primary key
  4. Remove the other 2 columns as keys

However, when I use the UI provided, it never works. Sometimes it'll just look like it tries to do something but it never changes when I refresh the view of the columns. It occasionally creates a temp table that looks like it tried to do some of the operation, but that never gets copied/overwrites the original table that I'm trying to change.

When I try using a query, the changes don't show up either. Here are the queries I think I need:

    SELECT * from history WHERE id is NULL     <---- This shows 0 results

    ALTER TABLE history
    ALTER COLUMN id int NOT NULL

    ALTER TABLE history ADD PRIMARY KEY (id)

    ALTER TABLE history
    DROP CONSTRAINT userId
    DROP CONSTRAINT name
    GO

I've only gotten to the attempt to disallow NULLs and to add the primary key for the id column. It doesn't seem to work. Can someone point me in the right direction? Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ckbhodge
  • 913
  • 2
  • 9
  • 19

2 Answers2

94

Assuming that your current primary key constraint is called pk_history, you can replace the following lines:

ALTER TABLE history ADD PRIMARY KEY (id)

ALTER TABLE history
DROP CONSTRAINT userId
DROP CONSTRAINT name

with these:

ALTER TABLE history DROP CONSTRAINT pk_history

ALTER TABLE history ADD CONSTRAINT pk_history PRIMARY KEY (id)

If you don't know what the name of the PK is, you can find it with the following query:

SELECT * 
  FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
 WHERE TABLE_NAME = 'history'
competent_tech
  • 44,465
  • 11
  • 90
  • 113
  • thanks. tried these (after using your query to find the PK name: "PK_history") but the UI is still showing the original 2 columns as keys and the id column without. i don't get an error message. perhaps it's due to the id column still allowing nulls? – ckbhodge Jan 13 '12 at 00:49
  • 1
    Did you do a refresh in the UI? I strongly suspect that they could be foreign keys and not the PK. You can `SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 'history'` to determine which constraint each of the columns in the table is associated with. – competent_tech Jan 13 '12 at 00:54
  • Yep, refreshed the UI (even closed out the tab and reopened). I've updated the results of the above query at the top of the question. Thanks! – ckbhodge Jan 13 '12 at 01:06
  • Ok, it just sounds like you may not have run the commands in order? You should run your first two commands (check the DB, then convert id to not null) then my two command (drop the existing constraint, then add a new one back in). Can you try it in that order and see if it makes a difference or if there are any errors reported? – competent_tech Jan 13 '12 at 01:11
  • Trying it again. I'm noticing now that the query to set the id column to not allow nulls actually keeps showing it is running every few seconds in the bottom right corner (in a very subtle way). Perhaps I didn't wait long enough the last few times before I clicked somewhere else on the UI? – ckbhodge Jan 13 '12 at 01:17
  • If it's a big table, it could take awhile. You should get some sort of positive acknowledgement at some point from one of the actions. – competent_tech Jan 13 '12 at 01:39
  • It is quite a large table - over 3.5M rows. I'll leave that tab open and check back in a few hours. Thanks! – ckbhodge Jan 13 '12 at 02:09
  • The query for setting the id column to disallow NULLs seems to still be running (yay for unclear UI!). I'm considering creating a new column that already is set to not allow NULLs then copying to it. – ckbhodge Jan 13 '12 at 21:43
  • Well, looks like both of those operations (disallow NULLs on the id column and creating a new column that doesn't allow NULLs) are still running, days later. I've opened a new tab to refresh the view and I don't see any changes. Do you think I should just create a new table and copy over the data? – ckbhodge Jan 15 '12 at 02:29
  • That definitely sounds like the easiest course of action at this point. – competent_tech Jan 15 '12 at 02:31
  • Thanks for your help. I've now created a new table and copied over the values. I've also installed Microsoft SQL Server Management Studio and connected to the DB through there instead of the awful web interface. – ckbhodge Feb 02 '12 at 01:43
1

Necromancing.
It looks you have just as good a schema to work with as me... Here is how to do it correctly:

In this example, the table name is dbo.T_SYS_Language_Forms, and the column name is LANG_UID

-- First, chech if the table exists...
IF 0 < (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE = 'BASE TABLE'
    AND TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'T_SYS_Language_Forms'
)
BEGIN
    -- Check for NULL values in the primary-key column
    IF 0 = (SELECT COUNT(*) FROM T_SYS_Language_Forms WHERE LANG_UID IS NULL)
    BEGIN
        ALTER TABLE T_SYS_Language_Forms ALTER COLUMN LANG_UID uniqueidentifier NOT NULL 

        -- No, don't drop, FK references might already exist...
        -- Drop PK if exists 
        -- ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT pk_constraint_name 
        --DECLARE @pkDropCommand nvarchar(1000) 
        --SET @pkDropCommand = N'ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT ' + QUOTENAME((SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
        --WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
        --AND TABLE_SCHEMA = 'dbo' 
        --AND TABLE_NAME = 'T_SYS_Language_Forms' 
        ----AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
        --))
        ---- PRINT @pkDropCommand 
        --EXECUTE(@pkDropCommand) 

        -- Instead do
        -- EXEC sp_rename 'dbo.T_SYS_Language_Forms.PK_T_SYS_Language_Forms1234565', 'PK_T_SYS_Language_Forms';


        -- Check if they keys are unique (it is very possible they might not be) 
        IF 1 >= (SELECT TOP 1 COUNT(*) AS cnt FROM T_SYS_Language_Forms GROUP BY LANG_UID ORDER BY cnt DESC)
        BEGIN

            -- If no Primary key for this table
            IF 0 =  
            (
                SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
                WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
                AND TABLE_SCHEMA = 'dbo' 
                AND TABLE_NAME = 'T_SYS_Language_Forms' 
                -- AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
            )
                ALTER TABLE T_SYS_Language_Forms ADD CONSTRAINT PK_T_SYS_Language_Forms PRIMARY KEY CLUSTERED (LANG_UID ASC)
            ;

            -- Adding foreign key
            IF 0 = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms') 
                ALTER TABLE T_ZO_SYS_Language_Forms WITH NOCHECK ADD CONSTRAINT FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms FOREIGN KEY(ZOLANG_LANG_UID) REFERENCES T_SYS_Language_Forms(LANG_UID); 
        END -- End uniqueness check
        ELSE
            PRINT 'FSCK, this column has duplicate keys, and can thus not be changed to primary key...' 
    END -- End NULL check
    ELSE
        PRINT 'FSCK, need to figure out how to update NULL value(s)...' 
END 
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442