none
recomendaciones para columna ID [sql server 05] RRS feed

  • Pregunta

  • Ocurre lo siguiente, tengo una tabla en la cual estan los ids,  nombres, apellidos y fecha de nacimiento de las personas a quien les doy entrada, ahora:

    he hecho un UPDATE en el cual me toma la primera letra del primer nombre, primera letra del primer apellido, dia y mes (en numeros) de nacimiento, estos son usados como id luego del update, osea, al darles entrada a los datos puedo poner digamos un ID 0 (la columna ID es de tipo CHAR) y con este update cambio el ID como realmente lo necesito. EJEMPLO:

    hago la siguiente insercion (entrada):

    INSERT INTO p_estudiante(id, n_est, a_est, f_nac)
    	VALUES('0', 'Kent Alejandro', 'Pina Zabala', '1990-25-05');
    
    

    el update es:

    UPDATE p_estudiante
    SET id = SUBSTRING(n_est, 1, 1) +
    	   SUBSTRING(a_est, 1, 1) + 
    	   REPLACE((SUBSTRING((CONVERT(CHAR, f_nac, 101)), 1, 5)), '/','')
    WHERE id IS NOT NULL
    

    luego de hacer el update, obtengo el resultado deseado:

     

    id     n_est                          a_est                              f_nac

    ------ ------------------------- ------------------------- -----------------------

    KP0525 Kent Alejandro            Pina Zabala               1990-05-25 00:00:00.000

    ..............

    entonces con esto viene una serie de preguntas:

    1.(en caso de que sea posible) ¿como puedo hacer que el campo ID tenga estas condiciones al momento de ser creada la tabla?

    2.¿es recomendable un procedimiento almacenado?

    3.¿alguna otra instruccion que pueda hacer esto automaticamente al momento de dar entrada al nombre, apellido, fecha de cumpleaños?

    ¿COMO HACERLO? EN CASO DE QUE ALGUNA APLIQUE...

    NOTA: esto es para la columna ID que es la llave primaria de la tabla.

     

    GRACIAS DE ANTEMANO :D


    Kent Piña [Republica Dominicana]
    domingo, 23 de enero de 2011 23:57

Respuestas

  • Si necesitas la columna como clave primaria, entonces el trigger no te sera de ayuda, ya que este se dispara despues de insertar y las restricciones como clave primaria son chequeadas antes de que el trigger se dispare.

    Si no te fijastes bien en mi primera respuesta, la formula que estas usando para mantener ese ID puede dar como resultado valores duplicados y por lo tanto tendras diferentes personas compartiendo el mismo ID, como puedes ver en el script que adjunte. Otra cosa, si la columna ID es la clave primaria, entonces tendras que crear una restriccion y por lo tanto no podras tener dos filas con el mismo valor inicial '0', por lo que te veras obligado a insertar en esa tabla una sola fila a la vez.

    Mi sugerencia es que decistas de usar ese mecanismo ya que no es de fiar, debes mantener la unicidad de forma procedural y no declarativa que es la recomendada, debes actualizar la clave primaria lo cual se debe evitar se es posible. Ademas, una clave primaria se usa para definiri unicamente cada fila y no para poner una etiqueta a cada persona, pues los usuarios que usen el sistema no tiene por que recordar esos valores para poder accesar las filas.

    Solo has una prueba para que veas como fallara ese codigo. Por ejemplo, fallara si:

    - Insertas mas de una persona a la misma vez, pues dos filas no deben tener el mismo valor '0' en esa columna.

    - insertas dos personas con igual letra de inicio de nombre y apellido (paterno) en el mismo dia.

    Otra cosa, si la columna es calculada, entonces puedes usar la propiedad PERSISTED, y usar un indice unico por esa columna o una vista indexada para enforzar la unicidad en esa columna.

    Aqui te dejo otro script para que veas que puedes usar una columna calculada como clave primaria, y ademas para que notes que la formula para generar el ID no es optima.

    use tempdb;
    GO
    CREATE TABLE dbo.p_estudiante(
    n_est varchar(50), 
    a_est varchar(50), 
    f_nac datetime,
    id AS LEFT(n_est, 1) + LEFT(a_est, 1) + RIGHT('00' + LTRIM(DAY(f_nac)), 2) + RIGHT('00' + LTRIM(MONTH(f_nac)), 2) PERSISTED,
    CONSTRAINT PK_p_estudiante PRIMARY KEY NONCLUSTERED (id)
    )
    GO
    INSERT INTO dbo.p_estudiante(n_est, a_est, f_nac)
    VALUES('Kent Alejandro', 'Pina Zabala', '19900525');
    
    INSERT INTO dbo.p_estudiante(n_est, a_est, f_nac)
    VALUES('Salvador', 'Lopez', '19900525');
    GO
    -- esta fila dara error
    -- puesto que el valor KP2505 ya existe
    INSERT INTO dbo.p_estudiante(n_est, a_est, f_nac)
    VALUES('Kathy', 'Pino', '19900525');
    GO
    SELECT * FROM dbo.p_estudiante;
    GO
    DROP TABLE dbo.p_estudiante;
    GO
    
    

     


    AMB

    Some guidelines for posting questions...

    lunes, 24 de enero de 2011 14:24

Todas las respuestas

  • Eso lo puedes lograr con una columna calculada, pero no creo que sea un ID, si es que con esto quieres identificar unicamente una fila.

    Ejemplo:

    use tempdb;
    GO
    CREATE TABLE #p_estudiante(
    n_est varchar(50), 
    a_est varchar(50), 
    f_nac datetime,
    id AS LEFT(n_est, 1) + LEFT(a_est, 1) + RIGHT('00' + LTRIM(DAY(f_nac)), 2) + RIGHT('00' + LTRIM(MONTH(f_nac)), 2)
    )
    GO
    INSERT INTO #p_estudiante(n_est, a_est, f_nac)
    VALUES('Kent Alejandro', 'Pina Zabala', '19900525');
    
    INSERT INTO #p_estudiante(n_est, a_est, f_nac)
    VALUES('Kathy', 'Pino', '19900525');
    
    SELECT * FROM #p_estudiante;
    GO
    DROP TABLE #p_estudiante;
    GO
    

    Para que quieres usar esta columna [id]?

     


    AMB

    Some guidelines for posting questions...

    lunes, 24 de enero de 2011 0:56
  • la columna ID es el codigo que identifica cada persona, por eso lo necesito como llave primaria.

    si no fuera llave primaria fuea un exito la columna calculada.


    Kent Piña [Republica Dominicana]
    lunes, 24 de enero de 2011 1:07
  • bien señores, encontre una forma para hacer lo que necesito con un trigger... es mi primera vez que lo uso :D ha sido efectivo

    CREATE TRIGGER Actualizar
    ON Prueba.dbo.p_estudiante
    FOR INSERT
    AS
    BEGIN
    	UPDATE p_estudiante
    	SET
    		id = SUBSTRING(n_est, 1, 1) +
    			 SUBSTRING(a_est, 1, 1) + 
    			 REPLACE((SUBSTRING((CONVERT(CHAR, f_nac, 101)), 1, 5)), '/','')
    	WHERE id IS NOT NULL
    END
    

    HUNCHBACK, muy buena tu sugerencia, la tendre presente para esos casos de colum. calculadas. GRACIAS :D

    estoy abierto a mas sugerencias amigos :D


    Kent Piña [Republica Dominicana]
    lunes, 24 de enero de 2011 1:59
  • Si necesitas la columna como clave primaria, entonces el trigger no te sera de ayuda, ya que este se dispara despues de insertar y las restricciones como clave primaria son chequeadas antes de que el trigger se dispare.

    Si no te fijastes bien en mi primera respuesta, la formula que estas usando para mantener ese ID puede dar como resultado valores duplicados y por lo tanto tendras diferentes personas compartiendo el mismo ID, como puedes ver en el script que adjunte. Otra cosa, si la columna ID es la clave primaria, entonces tendras que crear una restriccion y por lo tanto no podras tener dos filas con el mismo valor inicial '0', por lo que te veras obligado a insertar en esa tabla una sola fila a la vez.

    Mi sugerencia es que decistas de usar ese mecanismo ya que no es de fiar, debes mantener la unicidad de forma procedural y no declarativa que es la recomendada, debes actualizar la clave primaria lo cual se debe evitar se es posible. Ademas, una clave primaria se usa para definiri unicamente cada fila y no para poner una etiqueta a cada persona, pues los usuarios que usen el sistema no tiene por que recordar esos valores para poder accesar las filas.

    Solo has una prueba para que veas como fallara ese codigo. Por ejemplo, fallara si:

    - Insertas mas de una persona a la misma vez, pues dos filas no deben tener el mismo valor '0' en esa columna.

    - insertas dos personas con igual letra de inicio de nombre y apellido (paterno) en el mismo dia.

    Otra cosa, si la columna es calculada, entonces puedes usar la propiedad PERSISTED, y usar un indice unico por esa columna o una vista indexada para enforzar la unicidad en esa columna.

    Aqui te dejo otro script para que veas que puedes usar una columna calculada como clave primaria, y ademas para que notes que la formula para generar el ID no es optima.

    use tempdb;
    GO
    CREATE TABLE dbo.p_estudiante(
    n_est varchar(50), 
    a_est varchar(50), 
    f_nac datetime,
    id AS LEFT(n_est, 1) + LEFT(a_est, 1) + RIGHT('00' + LTRIM(DAY(f_nac)), 2) + RIGHT('00' + LTRIM(MONTH(f_nac)), 2) PERSISTED,
    CONSTRAINT PK_p_estudiante PRIMARY KEY NONCLUSTERED (id)
    )
    GO
    INSERT INTO dbo.p_estudiante(n_est, a_est, f_nac)
    VALUES('Kent Alejandro', 'Pina Zabala', '19900525');
    
    INSERT INTO dbo.p_estudiante(n_est, a_est, f_nac)
    VALUES('Salvador', 'Lopez', '19900525');
    GO
    -- esta fila dara error
    -- puesto que el valor KP2505 ya existe
    INSERT INTO dbo.p_estudiante(n_est, a_est, f_nac)
    VALUES('Kathy', 'Pino', '19900525');
    GO
    SELECT * FROM dbo.p_estudiante;
    GO
    DROP TABLE dbo.p_estudiante;
    GO
    
    

     


    AMB

    Some guidelines for posting questions...

    lunes, 24 de enero de 2011 14:24
  • entonces podria tener una columna integer con un identity com oprimaria y la del ID ya como otro campo y no como una llave primaria??? seria mejor asi y obtenerla como una columna calculada y no de la forma en la cual lo hice con el trigger?
    Kent Piña [Republica Dominicana]
    lunes, 24 de enero de 2011 22:24