web-dev-qa-db-fra.com

Modifier la colonne de clé primaire dans SQL Server

MISE À JOUR

Voici les contraintes résultant de la requête

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

Voici le résultat de la requête

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

CONSTRAINT_NAME   CONSTRAINT_TYPE  IS_DEFERRABLE  INITIALLY_DEFERRED
PK_history        PRIMARY KEY      NO             NO

FIN MISE À JOUR

Mon hôte fournit une interface à ma base de données SQL Server via ASP.NET Enterprise Manager.

J'ai 3 colonnes dans ma table history:

  • userId (clé, int, NULL non autorisé)
  • name (clé, chaîne, NULL non autorisé)
  • id (pas de clé, int, NULL autorisé)

Je veux que la colonne id soit la seule clé.

Pour ce faire, je crois avoir besoin de:

  1. Assurez-vous qu'il n'y a pas de NULL dans cette colonne pour aucune ligne
  2. Définir la colonne pour ne pas autoriser les valeurs NULL
  3. Ajouter la colonne en tant que clé primaire
  4. Supprimer les 2 autres colonnes sous forme de clés

Cependant, lorsque j'utilise l'interface utilisateur fournie, cela ne fonctionne jamais. Parfois, on dirait qu'il tente de faire quelque chose, mais cela ne change jamais lorsque j'actualise la vue des colonnes. Cela crée parfois une table temporaire qui ressemble à une tentative d'opération, mais qui n'est jamais copiée/écrasée par la table d'origine que je tente de modifier.

Lorsque j'essaie d'utiliser une requête, les modifications n'apparaissent pas non plus. Voici les questions dont je pense avoir besoin:

    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

Je suis seulement arrivé à la tentative d'interdire les valeurs NULL et d'ajouter la clé primaire pour la colonne id. Cela ne semble pas fonctionner. Quelqu'un peut me diriger dans la bonne direction? Merci!

48
ckbhodge

En supposant que votre contrainte de clé primaire actuelle s'appelle pk_history, vous pouvez remplacer les lignes suivantes:

ALTER TABLE history ADD PRIMARY KEY (id)

ALTER TABLE history
DROP CONSTRAINT userId
DROP CONSTRAINT name

avec ces:

ALTER TABLE history DROP CONSTRAINT pk_history

ALTER TABLE history ADD CONSTRAINT pk_history PRIMARY KEY (id)

Si vous ne connaissez pas le nom de la PK, vous pouvez le trouver avec la requête suivante:

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

Nécromancie.
Il semble que vous ayez un aussi bon schéma pour travailler que moi ... Voici comment le faire correctement:

Dans cet exemple, le nom de la table est dbo.T_SYS_Language_Forms et le nom de la colonne est 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 
1
Stefan Steiger