Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Insertar datos desde una tabla a otra en una sola sentencia. (https://www.clubdelphi.com/foros/showthread.php?t=97178)

delphi50jmb 21-01-2025 04:07:45

Insertar datos desde una tabla a otra en una sola sentencia.
 
Hola amigos.
Tengo que realizar una inserción de datos a un archivo de toma de inventario. Los datos ajustados se toman desde otro archivo.

El punto es que tengo que grabar los datos ajustados en el archivo TOMAINVTARIO, pero estos deben ir con un números de folio de ajuste, el cual no existe en la tabla inventario.

Entonces la pregunta es: Como puedo tomar datos desde una tabla para llevarlos a otra, incorporando ademas un datos externo?. En este caso, la variable "Folio". Es posible hacer esto, en una sola sentencia SQL?..

Aquí va el como lo estoy haciendo. Alguna idea?.

Código SQL [-]
  SQL_String.SQL.Clear;
   SQL_String.SQL.Append(
            'INSERT INTO ' + 'TomaInvtario ' +
                         '(Folio, Codigo, Nombre, ExistAct, Fisico) ' +
            'SELECT ' +
                         EdFolio.Text +     <<---- Este dato es externo, ajeno a la tabla Inventario.
                        'Codigo, ' +
                        'Nombre, ExistAct, ExistTMP ' +
            'FROM '  + 'Inventario ' +
            'WHERE ' +  'Inventario.Familia   = ' + QuotedStr(EdFamilia.Text)); 

   SQL_String.ExecSQL(False);

Saludos.
Gracias.

Casimiro Notevi 21-01-2025 09:19:11

Hola, no entiendo el problema :confused:

Neftali [Germán.Estévez] 21-01-2025 10:04:31

La sentencia SELECT..INTO parece que es correcta.
Dependerá de qué tipo sea el campo Folio, es posible que te de errores de sintaxis.

Como bien dice [Casimiro] te falta aclarar cual es el problema ¿Obtienes algún error? ¿No hace lo que deseas o esperas?
...

oscarac 21-01-2025 15:57:04

el valor del folio debe ser un texto

Código SQL [-]
SQL_String.SQL.Clear;
   SQL_String.SQL.Append(
            'INSERT INTO ' + 'TomaInvtario ' +
                         '(Folio, Codigo, Nombre, ExistAct, Fisico) ' +
            'SELECT ' +
                         QuotedStr(EdFolio.Text)+
                        'Codigo, ' +
                        'Nombre, ExistAct, ExistTMP ' +
            'FROM '  + 'Inventario ' +
            'WHERE ' +  'Inventario.Familia   = ' + QuotedStr(EdFamilia.Text)); 

   SQL_String.ExecSQL(False);

Pruebalo asi

delphi50jmb 21-01-2025 18:37:06

Hola.
Gracias a todos por responder.
No sabia como incorporar una vbariable externa a la sentencia "SELECT... INSERT INTO".

Con la respuesta de "oscarac", logre resolver el problema. Habia que encerrar el componente EdFolio.Text, en un: QuotedStr().

Pero curiosamente ahora se me presenta otro problema. Intenta grabar, pero me indica que el primer registro viola el indice primario y no graba.

Ejemplo:
En el archivo de Ajustes de inventario, tenemos:

Código SQL [-]
Folio: 1
Codigo         Nombre                        Fisico
----------------------------------------------------
7795320000122  XARELTO 15mg. 28 COMP.            15
7800008011502  ISQUELLIUM 4mg. 30 COMP.           6
7800059002825  CAVAMED 5mg. x 30 COMP.           12
8437024105084  RIXOVITAE COM 10mg COMP. X 10      9

luego de ejecutar la sentencia:
Código SQL [-]
SQL_String.SQL.Clear;
   SQL_String.SQL.Append(
            'INSERT INTO ' + 'TomaInvtario ' +
                         '(Folio, Codigo, Nombre, ExistAct, Fisico) ' +
            'SELECT ' +
                         QuotedStr(EdFolio.Text)+
                        'Codigo, ' +
                        'Nombre, ExistAct, ExistTMP ' +
            'FROM '  + 'Inventario ' +
            'WHERE ' +  'Inventario.Familia   = ' + QuotedStr(EdFamilia.Text)); 

   SQL_String.ExecSQL(False);

Me entrega el siguiente error, y no graba:

Código SQL [-]
  violation of PRIMARY or UNIQUE KEY 
  constraint "PK_TOMAINVTARIO" on table 'TOMAINVTARIO'
  Problematic key value is ("FOLIO:" = 1, "CODIGO" = '7795320000122')

La tabla 'TOMAINVTARIO', esta actualmente vacia. Estos son los primeros registros que se grabaran.

El indice primario esta compuesto por: Folio, Codigo. (Donde: Folio, es numerico, y Codigo, AlfaNumerico(20)).

Alguna idea.
Saludos.
Gracias.

Casimiro Notevi 21-01-2025 19:57:42

¿Pero, "folio" es único?

delphi50jmb 21-01-2025 21:30:05

Hola Casimiro.
Folio, es unico para cada proceso de toma de inventario. Pero se repite al grabar la toma de ajustes de inventario. Tomando el ejemplo anterior, el archivo deberia quedar asi:

Código SQL [-]
Folio     Codigo         Nombre                        Fisico
------------------------------------------------------------------------
  1       7795320000122  XARELTO 15mg. 28 COMP.            15  
  1       7800008011502  ISQUELLIUM 4mg. 30 COMP.           6
  1       7800059002825  CAVAMED 5mg. x 30 COMP.           12
  1       8437024105084  RIXOVITAE COM 10mg COMP. X 10      9

En este caso, el Folio se repite, pero cada codigo es unico por cada producto. Y el Primary Key, esta formado por: Folio, Codigo.
Para una segunda toma de inventario, el Folio seria 2, y en otra posterior 3, y asi sucesivamente.

Pero me reclama que el primer registro viola el primary Key, aun cuando todavia no hay ningun registro en la tabla de tomas de inventario.

Alguna sugerencia?

Saludos.
Gracias.

Casimiro Notevi 22-01-2025 11:04:27

Si no hay ningún registro entonces es que estás haciendo pruebas conectado a una base de datos que sí tiene registros.

oscarac 22-01-2025 14:14:33

chequea como tienes las llaves primary
chequea tambien si es que llega a grabar algun registro
chequea el valor de folio
ojo si es una tabla mysql las claves primary son diferentes cuando estan en innodb solo uedes usar un campo pero cuando esta en MyIsam puedes generar llaves primary key con combinaciones de campos

si es SqlServer funciona como MyIsam

cloayza 22-01-2025 15:05:28

Estimado colega delphi50jmb, si me lo permite, le propongo dos opciones de código. Le sugiero en lo posible utilizar parametros para pasar valores a sentencias SQL.

Clarifica mucho el código.

Código Delphi [-]
Opcion 1:

SQL_String.SQL.Clear;
SQL_String.SQL.Add('INSERT INTO TomaInvtario (Folio, Codigo, Nombre, ExistAct, Fisico)');
SQL_String.SQL.Add('SELECT :Folio as Codigo, Nombre, ExistAct, ExistTMP ');
SQL_String.SQL.Add('FROM Inventario');
SQL_String.SQL.Add('WHERE Inventario.Familia = :Familia');

//Utilización de Parametros para pasar valores a la sentencia SQL.
SQL_String.ParamByName('Folio').AsString  :=EdFolio.Text;
SQL_String.ParamByName('Familia').AsString:=EdFamilia.Text;

SQL_String.ExecSQL(False);

Opcion 2:
SQL_String.SQL.Clear;
SQL_String.SQL.Add('INSERT INTO TomaInvtario (Folio, Codigo, Nombre, ExistAct, Fisico)');
SQL_String.SQL.Add(Format('SELECT %s as Codigo, Nombre, ExistAct, ExistTMP',[QuotedStr(EdFolio.Text)]));

SQL_String.SQL.Add('FROM Inventario');
SQL_String.SQL.Add('WHERE Inventario.Familia = :Familia');

//Utilización de Parametros para pasar valores a la sentencia SQL.
SQL_String.ParamByName('Familia').AsString:=EdFamilia.Text;

SQL_String.ExecSQL(False);
[QUOTE
En cuanto al error de primary key

Cita:

violation of PRIMARY or UNIQUE KEY
constraint "PK_TOMAINVTARIO" on table 'TOMAINVTARIO'
Problematic key value is ("FOLIO:" = 1, "CODIGO" = '7795320000122')
Es muy claro que ya existe un registro con esos atributos de Folio y Codigo, le sugiero comprueba la existencia de esos, realizando una consulta con esos parametros.

Saludos cordiales

delphi50jmb 22-01-2025 23:18:00

Hola casimiro, cloayza, oscarac.
Tengo solo una base de datos con la cual hago las pruebas. y las vacio para hacer pruebas. Por eso me llama la atencion el problema de Primary key.
De todas maneras volvere a revisar. En este momento estoy trabajando con bases Firebird.

Tambien probare las sugerencias y comentarios de cloayza, para trabajar mas estructurado.

Volvere a probar y les comento.

Saludos.
Gracias.

delphi50jmb 23-01-2025 03:08:01

Hola casimiro, cloayza, oscarac.
Tenian razon. Revise cuidadosamente la base de datos y el codigo delphi. Y sin darme cuenta estaba haciendo dos veces el llamado al mismo procedimiento. Corregi ese error y ahora funciono perfetamente.

Gracias a todos por su paciencia y comentarios.

Tendre presente los comentarios de cloayza, para tener un codigo SQL mas estructurado.

Saludos y gracias.
Jose Miguel B.


La franja horaria es GMT +2. Ahora son las 11:14:29.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi