locked
Funcion para insertar datos y calcular letra del dni

    Pregunta

  • Hola a todos!!! 
    Bueno estoy haciendo un ejercicio que consiste en hacer una funcion. 

    Supongamos que yo tengo una tabla llamada TempleDNI con tres campos (nombre,dni,letra). La funcion consiste en que yo pongo un DNI (sin la letra) y se guarda en el campo DNI, ademas la funcion tambien tiene que calcular su letra y guardarla en el campo letra. Devolviendo la letra del dni.

    Yo lo tengo hecho asi: 

    create function funcion6 (@dni int)
    returns char(1) 
    as
    begin
    declare @letra char(1), @num int
    set @num=@dni-((@dni/23)*23)
    set @letra=(SUBSTRING('TRWAGMYFPDXBNJZSQVHLCKE', @num+1, 1))
    if (len(@dni)=8)
    	begin
    	insert into TempleDNI (dni) values (@dni)
    	insert into TempleDNI (letra) values (@letra)
    	end
    return @letra
    end
    Pero lo tengo mal, me da un error:

    Uso no válido de operador con efectos secundarios 'INSERT' dentro de una función.

    Alguien sabe que es lo que tengo mal??? Muchas gracias!!!




    miércoles, 17 de marzo de 2010 14:53

Respuestas

  • Echa un vistazo a la documentación sobre la creación de funciones definindas por el usuario. Hay un apartado que especifica las instrucciones válidas, dentro de las cuales no está ese INSERT: http://msdn.microsoft.com/es-es/library/ms191320.aspx

    Para que te funcione correctamente deberías llamar a la función en de la instrucción INSERT, algo como

    DECLARE @dni INT, @letra CHAR(1);
    
    SET @dni = 123456;
    
    SET @letra = dbo.funcion6(@dni);
     
    INSERT TempleDNI (dni, letra) VALUES (@dni, @letra);
    miércoles, 17 de marzo de 2010 15:03
  • Hola.

    Sí, es imposible. Te puedes crear un procedimiento almacenado que lo haga, o hacer un 
    "insert MiTabla select * from dbo.Mifuncion"

    pero no podrás hacerlo directamente con la función. 


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    miércoles, 17 de marzo de 2010 17:45
    Moderador

Todas las respuestas

  • Echa un vistazo a la documentación sobre la creación de funciones definindas por el usuario. Hay un apartado que especifica las instrucciones válidas, dentro de las cuales no está ese INSERT: http://msdn.microsoft.com/es-es/library/ms191320.aspx

    Para que te funcione correctamente deberías llamar a la función en de la instrucción INSERT, algo como

    DECLARE @dni INT, @letra CHAR(1);
    
    SET @dni = 123456;
    
    SET @letra = dbo.funcion6(@dni);
     
    INSERT TempleDNI (dni, letra) VALUES (@dni, @letra);
    miércoles, 17 de marzo de 2010 15:03
  • Osea que no puedo poner un INSERT que modifique una tabla, en una funcion definida por usuario??

    En el documento que miré dice que se puede usar una instruccion INSERT que modifique las variables de tabla locales de la función.
    No lo entiendo porque cuando yo hago un insert no estoy modificando las variables locales de la funcion, sino las tablas.

    La verdad que ahora mismo no se que tipo de insert es el válido para una funcion definida por usuario.

    Bueno estoy echa un lio, si alguien me ayuda a aclararme se lo agradeceria!!! XD
    miércoles, 17 de marzo de 2010 16:23
  • Por eso justamente te da el error: estás tratando de modificar datos de una tabla externa. Básicamente puedes tratar (insert, update, delete) los datos de variables tipo tabla que crees dentro de esa función.

    Por cierto, aunque te funcionara, tal y como lo tienes estarías insertando dos registros: uno con el dni y otro con la letra. Tendrías que haber hecho algo como lo que te ponía en mi ejemplo

    miércoles, 17 de marzo de 2010 16:30
  • Hola.

    No puedes realizar una inserción en una tabla física, sólo en variables de tipo tabla.

    Si miras en http://msdn.microsoft.com/en-us/library/ms186755.aspx, podrás ver que hay funciones que devuelven tablas. Esas tablas pueden ser cargadas en la función y hay que insertar en ellas para cargarlas.

    En el link que te paso tienes ejemplos de ello (el C). Si no logras aclararte, nos dices.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    miércoles, 17 de marzo de 2010 16:34
    Moderador
  • Bueno yo acabo de hacer esto, puede que este fatal, no se rian de mi jaja XD

    create function funcion6 (@dni int)
    returns @datos table
    (dni int,letra char(1)) 
    as
    begin
    declare @letra char(1), @num int
    
    set @num=@dni-((@dni/23)*23) /*Operacion para calcular letra del DNI*/
    set @letra=(SUBSTRING('TRWAGMYFPDXBNJZSQVHLCKE', @num+1, 1)) /*Almacenar letra en la variable @letra*/
    
    insert into datos (dni,letra) values (@dni,@letra)
    return 
    end

    ¿Está bien? lo almacené todo en una variable de tipo TABLE. Y si esta bien, ¿como puedo ver el resultado? porque al ejecutarlo pongo: select dbo.funcion6(45760896) y me da un error:

    No se encuentra la columna "dbo" o la función definida por el usuario o agregado "dbo.funcion6"; o bien, el nombre es ambiguo.

    miércoles, 17 de marzo de 2010 17:10
  • Hola.

    Sería "select * from dbo.funcion6(45677134)". Ten en cuenta que es una tabla y la debes consultar como tal.



    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    miércoles, 17 de marzo de 2010 17:11
    Moderador
  • Gracias qwalgrande ya puedo ver el resultado y me sale bien.

    Bueno lo que no me quedo bastante claro es una cosa. ¿Entonces es imposible crear una funcion para insertar esos datos en la tabla que yo me habia creado antes (TempleDNI)?
    miércoles, 17 de marzo de 2010 17:21
  • No, tampoco te va a dejar eso por la misma razón que la anterior. Las funciones de usuario no están pensadas para hacer lo que intentas, sino para hacer cálculos que puedas usar como cualquier otra función de sistema (como GETDATE(), LOWER, UPPER, etc, etc, etc).

    Tienes que pensarlo de forma separada: crea la función que te ayude a calcular la letra del DNI, y luego la usas para hacer el INSERT.
    • Propuesto como respuesta Carlos Sacristan miércoles, 17 de marzo de 2010 17:25
    miércoles, 17 de marzo de 2010 17:25
  • Vale ahora lo entiendo. lo que pasa es que en el enunciado del ejercico me decia: "Crea una funcion que actualizará la tabla,devolviendo la letra del DNI". No entiendo por qué dice que la actualice si no se puede hacer desde una funcion de usuario.
    miércoles, 17 de marzo de 2010 17:32
  • Hola.

    Sí, es imposible. Te puedes crear un procedimiento almacenado que lo haga, o hacer un 
    "insert MiTabla select * from dbo.Mifuncion"

    pero no podrás hacerlo directamente con la función. 


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    miércoles, 17 de marzo de 2010 17:45
    Moderador
  • Entendido, ya esta, problema solucionado XD

    Muchas gracias a todos, de verdad!!!

    Un abrazo!!
    miércoles, 17 de marzo de 2010 17:50