• Publicidad

Tengo un problema cuando ejecuto el comando execute

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Tengo un problema cuando ejecuto el comando execute

Notapor marcoamoncada » 2012-09-01 21:41 @945

Voy a platicar del tema: cuando ejecuto el comando execute en uno de mis programas me dice que la sintaxis está mal. Le he buscado pero no le encuentro. No sé si alguien pudiera ayudarme.

Estoy manejando una base de datos MySQL, la cual le inserto registros y los actualizo, pero cuando los selecciona y trata de ejecutar el módulo execute me da problemas.

Este programa funciona bien:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use strict;
  4. use DBI;
  5.  
  6. # Variables
  7. my $str = shift || &asigna_variable;
  8. my $username = '***********';
  9. my $password = '********';
  10. my $database = '********';
  11. my $server = '**********';
  12. my $fin;
  13.  
  14. # Remove end-of-line from input
  15. chomp $str;
  16.  
  17. my ($palabra_a,$campo,$tipo,$valor1,$valor2)=split(/\=/,$str);
  18.  
  19. my $table="Variables";
  20. my $campo_1="Variable";
  21. my $campo_2="Indicador";
  22. my $campo_3="Valor_Alf";
  23. my $campo_4="Valor_Num";
  24. my $comando_db="select * from Mundo where Mundo=8;";
  25. # Get the rows from database
  26. my $dbh = DBI->connect("DBI:mysql:$database;host=$server", $username, $password) || die "Could not connect to database: $DBI::errstr";
  27. my $sth = $dbh->prepare($comando_db)                            || die "$DBI::errstr";
  28. #$sth->bind_param(1, "%$str%");
  29. $sth->execute();
  30.  
  31. # Print number of rows found
  32. if ($sth->rows < 0) {
  33.     print "Sorry, no domains found.\n";
  34. } else {
  35.     printf ">> Found %d domains\n", $sth->rows;
  36.     # Loop if results found
  37.     while (my $results = $sth->fetchrow_hashref) {
  38.         my $mundo = $results->{Mundo}; # get the domain name field
  39.         my $numero_pueblos = $results->{Numero_Pueblos}; # get the URL field
  40.         my $indicador = $results->{Indicador}; # get the URL field
  41.         my $monedas = $results->{Monedas}; # get the URL field
  42.         printf "    +--- \e[1;42m %s (%s)\e[0m\n", $mundo, $numero_pueblos, $indicador, $monedas;
  43.     }
  44. }
  45. exit;
  46.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Este programa termina mal:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub select_db2
  2. {
  3.         print "$year/$mon/$mday:$hour:$min:select_db2 entra \n";
  4.         my $dbh=$_[$numero_0];
  5.         my $table=$_[$numero_1];
  6.         my $where=$_[$numero_2];
  7.  
  8.         &desconecta_db2($dbh);
  9.         my $dbh=&conecta_db2;
  10.  
  11.         my $comando_db="select * from $table $where;";
  12.         print "################################################################ \n";
  13.         print "$comando_db                                                      \n";
  14.         print "################################################################ \n";
  15.         my $sth = $dbh->prepare("$comando_db") || die "$DBI::errstr";
  16.         my $status=$sth->execute();
  17.         if(!defined $status)
  18.         {
  19.                 print "################################################################\n";
  20.                 print "$year/$mon/$mday:$hour:$min:$table:ERROR:$DBI::errstr \n";
  21.                 print "################################################################\n";
  22.                 $status=$numero_1;
  23.                 exit;
  24.         }
  25. }
  26. sub desconecta_db2
  27. {
  28.         print "$year/$mon/$mday:$hour:$min:desconecta_db2 entra \n";
  29.         my $dbh=$_[$numero_0];
  30.  
  31.         # Disconnect
  32.         #$sth->finish;
  33.         $dbh->disconnect;
  34. }
  35. sub conecta_db2
  36. {
  37.         print "$year/$mon/$mday:$hour:$min:conecta_db2 entra \n";
  38.         my $dbh = DBI->connect("DBI:mysql:$al;host=$am", $ak, $an) || die "Could not connect to database:$DBI::errstr";
  39.         print "$dbh \n";
  40.         return($dbh);
  41. }
  42.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


El error que manda el print() es este:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. 2012/9/1:21:3:carga_db2 entra
  2. 2012/9/1:21:3:select_mundo entra
  3. 2012/9/1:21:3:select_db2 entra
  4. 2012/9/1:21:3:desconecta_db2 entra
  5. 2012/9/1:21:3:conecta_db2 entra
  6. DBI::db=HASH(0x9fcd8c8)
  7. ################################################################       
  8. select * from Guerras.Mundo where Mundo=RL must be absolute
  9. Content-Type: text/plain
  10. Client-Date: Sun, 02 Sep 2012 02:03:59 GMT
  11. Client-Warning: Internal response
  12.  
  13. 400 URL must be abs;                                                   
  14. ################################################################       
  15. ################################################################
  16. 2012/9/1:21:3:Guerras.Mundo:ERROR:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'must be absolute
  17. Content-Type: text/plain
  18. Client-Date: Sun, 02 Sep 2012 02:03:59' at line 1
  19. ################################################################
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Si ejecuto el primer programa corre bien, pero con este que tiene o está modulado, no.

El módulo execute corre bien en otra parte del programa, porque sí inserto los registros, pero, como vuelvo a repetir, cuando los desea imprimir los selecciona y no funciona.

¿Alguien habrá que sepa o que me dé un hilo? Le incluí que primero desconectara, para saber si ese era el problema, pero no.

Si le digo directamente la llave, en el módulo select:db2:

my $comando_db="select * from Mundo where Mundo=8;";

me da el error de que no hay registros:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. 2012/9/1:21:48:carga_db2 entra
  2. 2012/9/1:21:48:select_mundo entra
  3. 2012/9/1:21:48:select_db2 entra
  4. 2012/9/1:21:48:desconecta_db2 entra
  5. 2012/9/1:21:48:conecta_db2 entra
  6. DBI::db=HASH(0xa0dd9a8)
  7. ################################################################       
  8. select * from Mundo where Mundo=8;                                                     
  9. ################################################################       
  10. 1|DBI::st=HASH(0xa0ddc48)
  11. 1|DBI::st=HASH(0xa0ddc48)
  12. 2012/9/1:21:48:imprime_mundo entra
  13. >> Found 0 Guerras.Mundo
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Si ejecuto los comando directamente desde la terminal me da lo siguiente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using mysql Syntax Highlighting
  1. mysql> select * from Guerras.Mundo where Mundo=8;
  2. +-------+----------------+-----------+---------+-------------------+
  3. | Mundo | Numero_Pueblos | Indicador | Monedas | Monedas_Generadas |
  4. +-------+----------------+-----------+---------+-------------------+
  5. | 8     |              0 |         1 |       0 |                 0 |
  6. +-------+----------------+-----------+---------+-------------------+
  7. 1 row in set (0.08 sec)
  8.  
  9. mysql>
  10.  
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using mysql Syntax Highlighting
  1. mysql> describe Guerras.Mundo;
  2. +-------------------+-------------+------+-----+---------+-------+
  3. | Field             | Type        | Null | Key | Default | Extra |
  4. +-------------------+-------------+------+-----+---------+-------+
  5. | Mundo             | varchar(10) | NO   | PRI | NULL    |       |
  6. | Numero_Pueblos    | int(11)     | YES  |     | NULL    |       |
  7. | Indicador         | tinyint(1)  | YES  |     | NULL    |       |
  8. | Monedas           | int(11)     | YES  |     | NULL    |       |
  9. | Monedas_Generadas | int(11)     | YES  |     | NULL    |       |
  10. +-------------------+-------------+------+-----+---------+-------+
  11. 5 rows in set (0.21 sec)
  12.  
  13. mysql>
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Gracias.
marcoamoncada
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2011-06-06 22:41 @986

Publicidad

Re: Tengo un problema cuando ejecuto el comando execute

Notapor explorer » 2012-09-01 22:25 @975

Falta algo de código. Yo creo que está bien el código mostrado, pero no el que llama a select_db2.

En efecto, sobra el desconectar y conectar. Quítalo.

Lo que no me gusta es esto:

select * from Mundo where Mundo=8;

Nosotros sabemos que el primer 'Mundo' se refiere a una tabla llamada así, y el segundo 'Mundo' se refiere a un campo de esa tabla que se llama así.

Lo que tengo dudas es que MySQL sepa esa diferencia. De hecho, tu mismo llamas a la tabla 'Guerras.Mundo'.

En el caso del primer error, es muy posible que venga de no comprobar los argumentos que se le pasan a la función antes de hacer la consulta. En el error se indica simplemente que la sentencia SQL está mal construida debido a que se ha puesto un argumento sintácticamente erróneo a la cláusula WHERE. Y se ve que proviene de una consulta HTTP que ha salido mal.

Es recomendable el uso de "place-holders" en los prepare() en lugar de construir la sentencia SQL "a mano", como en la línea 11, ya que cualquier hacker te la podría preparar...

Imprescindible (bobby-tables.com, en inglés)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14477
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Tengo un problema cuando ejecuto el comando execute

Notapor marcoamoncada » 2012-09-02 07:17 @345

Efectivamente, el campo $DB2_Mundo, llega con datos erróneos, pero cuando yo mismo tecleo la sentencia en el programa me dice que no tiene registros encontrados.

Y MySQL sí sabe la diferencia, que una, la primera es la tabla, y el segundo 'mundo' efectivamente es nombre de una columna.

Sintáxis: [ Descargar ] [ Ocultar ]
  1. mysql> select * from Mundo where Mundo=8; 
  2. +-------+----------------+-----------+---------+-------------------+ 
  3. | Mundo | Numero_Pueblos | Indicador | Monedas | Monedas_Generadas | 
  4. +-------+----------------+-----------+---------+-------------------+ 
  5. | 8   |       0 |     1 |    0 |         0 | 
  6. +-------+----------------+-----------+---------+-------------------+ 
  7. 1 row in set (0.13 sec) 
  8.  
  9. mysql>  


El programa que funciona bien.

Desde su código está su corrida.

Sintáxis: [ Descargar ] [ Ocultar ]
  1. #!/usr/bin/perl -w 
  2.  
  3. use strict; 
  4. use DBI; 
  5.  
  6. # Variables 
  7. my $str = shift || &asigna_variable; 
  8. my $username = 'marcoamoncada'; # set your MySQL username 
  9. my $password = 'GuErRaS'; # set your MySQL password 
  10. my $database = 'Guerras'; # set your MySQL database name 
  11. my $server = 'local54'; # set your server hostname (probably localhost) 
  12. my $fin; 
  13.  
  14. # Remove end-of-line from input 
  15. chomp $str; 
  16.  
  17. my ($palabra_a,$campo,$tipo,$valor1,$valor2)=split(/\=/,$str); 
  18.  
  19. my $comando_db="select * from Mundo where Mundo=8;"; 
  20. # Get the rows from database 
  21. my $dbh = DBI->connect("DBI:mysql:$database;host=$server", $username, $password) || die "Could not connect to database: $DBI::errstr"; 
  22. my $sth = $dbh->prepare($comando_db)                 || die "$DBI::errstr"; 
  23. #$sth->bind_param(1, "%$str%"); 
  24. $sth->execute(); 
  25.  
  26. # Print number of rows found 
  27. if ($sth->rows < 0) { 
  28.   print "Sorry, no domains found.\n"; 
  29. } else { 
  30.   printf ">> Found %d domains\n", $sth->rows; 
  31.   # Loop if results found 
  32.   while (my $results = $sth->fetchrow_hashref) { 
  33.     my $mundo = $results->{Mundo}; # get the domain name field 
  34.     my $numero_pueblos = $results->{Numero_Pueblos}; # get the URL field 
  35.     my $indicador = $results->{Indicador}; # get the URL field 
  36.     my $monedas = $results->{Monedas}; # get the URL field 
  37.     my $monedas_generadas = $results->{Monedas_Generadas}; # get the URL field 
  38.     printf "  +--- \e[1;42m %s (%s) (%s) (%s) (%s) (%s)\e[0m\n", $mundo, $numero_pueblos, $indicador, $monedas; 
  39.   } 
  40. exit; 


La corrida
Sintáxis: [ Descargar ] [ Ocultar ]
  1. mrco1965@GUERRAS:~$ perl Perl/DB_Lista2.pl 
  2. #[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[C#[22Pperl Perl/DB_Lista2.pl 
  3. >> Found 1 domains 
  4.   +--- #[1;42m 8 (0) (1) (0) (0)#[0m 


El programa que me da error cuando lo ejecuto con la sentencia tecleada, me dice que no encuentra reglones
Sintáxis: [ Descargar ] [ Ocultar ]
  1. mrco1965@GUERRAS:~$ Sh/GUERRAS_R02V01.sh marcoamoncada GuErRaS###############################[1P 
  2. marcoamoncada 
  3. 20120902-06.45.38 
  4. Can't locate object method "fetchrow_hashref" via package "DBI::st=HASH(0xa27cea0)" (perhaps you forgot to load "DBI::st=HASH(0xa27cea0)"?) at /home/mrco1965/Php/Prueba/perl/Guerras-10.2.pl line 1952. 
  5. marcoamoncada 
  6. 20120902-06.45.52 


El código del programa que me está volviendo loco.
Sintáxis: [ Descargar ] [ Ocultar ]
  1. sub select_db2 
  2.     print "$year/$mon/$mday:$hour:$min:select_db2 entra \n"; 
  3.     my $dbh=$_[$numero_0]; 
  4.     my $table=$_[$numero_1]; 
  5.     my $where=$_[$numero_2]; 
  6.  
  7.     my $comando_db="select * from $table $where;"; 
  8.     my $comando_db="select * from Guerras.Mundo where Mundo=8;"; 
  9.     print "################################################################    \n"; 
  10.     print "$comando_db                            \n"; 
  11.     print "################################################################    \n"; 
  12.     my $sth = $dbh->prepare("$comando_db") || die "$DBI::errstr"; 
  13.     my $status=$sth->execute(); 
  14.     if(!defined $status) 
  15.     { 
  16.         print "################################################################\n"; 
  17.         print "$year/$mon/$mday:$hour:$min:$table:ERROR:$DBI::errstr \n"; 
  18.         print "################################################################\n"; 
  19.         $status=$numero_1; 
  20.         exit; 
  21.     } 
  22.  
  23.     my $status=$numero_1; 
  24.     my $lineas=$sth->rows; 
  25.     if (    $lineas <    $numero_0    ) { 
  26.         $status    =    $numero_0; 
  27.         print "    \n"; 
  28.         print "################################################################    \n"; 
  29.         print "$year/$mon/$mday:$hour:$min:select_db2 entra:$DBI:errstr        \n"; 
  30.         print "El numero de lineas o renglones de la tablas $table son $lineas    \n"; 
  31.         print "################################################################    \n"; 
  32.         exit; 
  33.     } 
  34.     elsif(    $lineas    ==    $numero_0    ) 
  35.     { 
  36.         print "    \n"; 
  37.         print "################################################################    \n"; 
  38.         print "El numero de lineas o renglones de la tablas $table son $lineas    \n"; 
  39.         print "################################################################    \n"; 
  40.         $status    =    $numero_0; 
  41.     } 
  42.  
  43.     my $datos="$status|$sth"; 
  44.     print "$datos \n"; 
  45.  
  46.     return($datos); 


las impresiones que hace:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. 2012/9/2:6:45:carga_db2 entra  
  2. 2012/9/2:6:45:select_mundo entra  
  3. 2012/9/2:6:45:select_db2 entra  
  4. ################################################################     
  5. select * from Guerras.Mundo where Mundo=8;                             
  6. ################################################################     
  7. 1|DBI::st=HASH(0xa27cea0)  
  8. 1|DBI::st=HASH(0xa27cea0)  
  9. 2012/9/2:6:45:imprime_mundo entra  
  10. >> Found 0 Guerras.Mundo 


select_mundo
Sintáxis: [ Descargar ] [ Ocultar ]
  1. sub select_mundo 
  2.     print "$year/$mon/$mday:$hour:$min:select_mundo entra \n"; 
  3.     my $dbh=$_[$numero_0]; 
  4.     my $table=$_[$numero_1]; 
  5.     my $llave=$_[$numero_2]; 
  6.  
  7.     my $where="where $llave=$DB2_Mundo"; 
  8.     my $status=&select_db2($dbh,$table,$where); 
  9.     print "$status \n"; 
  10.     return($status); 


Conectar con la base de datos
Sintáxis: [ Descargar ] [ Ocultar ]
  1. sub conecta_db2 
  2.     print "$year/$mon/$mday:$hour:$min:conecta_db2 entra \n"; 
  3.     my $dbh = DBI->connect("DBI:mysql:$al;host=$am", $ak, $an) || die "Could not connect to database:$DBI::errstr"; 
  4.     print "$dbh \n"; 
  5.     return($dbh); 


La subrutina de imprime_mundo y la línea que manda el error es el while
Sintáxis: [ Descargar ] [ Ocultar ]
  1. sub imprime_mundo 
  2.     print "$year/$mon/$mday:$hour:$min:imprime_mundo entra \n"; 
  3.     my $sth=$_[$numero_0]; 
  4.     my $table=$_[$numero_1]; 
  5.  
  6.     my $db2_sel_monedas; 
  7.     #my $lineas=$sth->rows; 
  8.  
  9.     printf ">> Found %d $table\n", $lineas; 
  10.     while (my $results = $sth->fetchrow_hashref) 
  11.     { 
  12.         my $mundo = $results->{Mundo}; 
  13.         my $numero_pueblos = $results->{Numero_Pueblos}; 
  14.         my $indicador = $results->{Indicador}; 
  15.         $db2_sel_monedas = $results->{Monedas};  
  16.         my $monedas_Generadas = $results->{Monedas_Generadas}; 
  17.         printf "  +--- \e[1;42m (%s) (%s) (%s) (%s) (%s)\e[0m\n", $mundo,$numero_pueblos,$indicador,$db2_sel_monedas,$monedas_generadas; 
  18.         my $table=$tabla_puntos; 
  19.         my $datos=&select_puntos($dbh,$table,$llave,$numero_1); 
  20.         my ($status,$sth)=split(/\|/,$datos); 
  21.         if($status==$numero_0) 
  22.         { 
  23.             &imprime_puntos($sth,$table); 
  24.  
  25.         } 
  26.     } 
  27.     my $datos="$db2_sel_monedas"; 
  28.     return($datos); 


Todos los comandos son los mismos que el programa lista DB_Lista2.pl, ya que fue lo que se generó para detectar que le hacía falta, tanto permisos como comandos de MySQL, etc.

El programa GUERRAS-10.2.pl, hace muchas cosas, y está muy largo. Solamente se incluyó, y funciona bien, la parte que se incluyó, fue que dejara una secuencia de datos en MySQL, lo cual esta parte está dando problemas, ya releí el código, ya chequeé los comandos y son los mismos, y en el mismo sistema, que es una máquina virtual donde se corre.

Gracias y espero que mis preguntas no te causen molestia.

Saludos

P.D.: me podrás echar un peine, para detectar el problema.
Con tanta prueba puede ser que le elimine algo de los campos para formar el select, pero cuando los tecleo yo, no funciona no sé por qué.

Desde el mismo sistema están corriendo los dos, con el mismo usuario.

Compañero, por qué, en un programa sí lee los registros, y desde otro programa no los lee, dice que no hay nada.

Las llamadas a la base de datos sí funcionan, ya que se han insertado registros desde el código, y se han actualizado registros, pero no se pueden seleccionar, desde el programa que me da problemas. Y eso me causa mucha confusión.

Me podrás echar un peine, gracias.
marcoamoncada
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2011-06-06 22:41 @986

Re: Tengo un problema cuando ejecuto el comando execute

Notapor explorer » 2012-09-02 10:15 @468

El primer error indica que $st no contiene un objeto DBI, así que hay un problema a la hora de pasar ese argumento.

La salida de

>> Found 0 Guerras.Mundo

es porque está comentada la línea 8 de imprime_mundo y la línea 10 está sacando el valor de $lineas de... no se sabe dónde.

Muy divertidas las variables $numero_0, $numero_1, $numero_2... ¿se pusieron para despistar a los espías o para fastidiar a los programadores? :lol:

Las líneas 8 y 9 de select_db2 definen la misma variable, así que eso me dice que no estás usando

use strict;

y sospecho de que tampoco tienes activado

use warnings;

En serio: los necesitas. Perl es tu mejor amigo a la hora de programar. Él mismo te dirá dónde están los primeros errores. Quizás tengas que escribir más my(), pero el programa quedará muy sólido.

El error grave está en el paso de $sth entre las funciones.

En la línea 44 de select_db2() dice
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     my $datos="$status|$sth";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Esa línea está interpolando las variables $status y $sth en cadena de caracteres. No hay problema con $status, porque contiene un valor escalar, pero $sth es un objeto, por lo que su interpolación será la versión texto del objeto. Por eso sale en pantalla "DBI::st=HASH(0xa27cea0)".

No sé cómo será select_puntos(), pero me da la sensación de que tendrá las mismas líneas que select_db2(), porque, al llegar a la línea 20 de imprime_mundo(),
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.         my $datos=&select_puntos($dbh,$table,$llave,$numero_1);
  2.         my ($status,$sth)=split(/\|/,$datos);
  3.         if($status==$numero_0)
  4.         {
  5.             &imprime_puntos($sth,$table);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
La línea 20 está recibiendo unos $datos desde select_puntos(), que según la línea 21, se trata de una cadena de caracteres. Esa cadena la partes con split() en la línea 21, y dejas el resultado en $status y $sth. En ese momento, esas variables siguen conteniendo cadenas de caracteres. Aunque la variable se llame $sth no significa que contenga un objeto DBI. Sólo es una cadena de caracteres.

No sé lo que hace imprime_puntos(), pero si ese método cree que $sth es un objeto DBI, se equivoca completamente.

El error es ese: pasar entre funciones la conversión a texto de un objeto DBI.

El código es un poco... lioso... Le faltan buenas técnicas de programación. Por ejemplo: cuando el programa se hace muy grande, es muy peligroso confiar en las variables globales. Y las variables locales con my() tienen su vida limitada al contexto donde se declaran. Por eso es importante trabajar bien con los argumentos que se pasan a las funciones.

Una cosa más: si quieres tener un sistema profesional de registrado, te recomiendo Log-Log4perl. Te abreviará mucho el código de logging.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14477
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Tengo un problema cuando ejecuto el comando execute

Notapor marcoamoncada » 2012-09-02 21:15 @927

El primer error indica que $st no contiene un objeto DBI, así que hay un problema a la hora de pasar ese argumento.
Me dices que estoy pasando mal la variable $dbh, según entiendo, lo voy a verificar y cambiar el paso de variable de una rutina a otra.

La salida de

>> Found 0 Guerras.Mundo

es porque está comentada la línea 8 de imprime_mundo y la línea 10 está sacando el valor de $lineas de... no se sabe dónde.
La línea 8 en imprime_mundo está comentada, porque decía que no estaba disponible, pero todo esto se debe a la primera contestación, que la variable de “dbi” que equivale $dbh, no llega correctamente.

Y si te das cuenta esta variable $lineas solamente se utiliza en la línea 10, no es la razón planteada, ya que después del select se imprime la cantidad de registros y estos son tomados de lo que selección, y está en cero, por la primera respuesta que $dbh, no llega correctamente.

Muy divertidas las variables $numero_0, $numero_1, $numero_2... ¿se pusieron para despistar a los espías o para fastidiar a los programadores? :lol:
No soy muy afán a utilizar muchas constantes como sería preguntar por 0, o preguntar por “******algún texto******” porque, cuando tienes que cambiar por alguna razón, cambias en todo el texto, como por ejemplo preguntar por 10. Y ahora vas a preguntar por 20, solamente así cambias una variable no tienes que revisar todo el código. Claro, los nombre de $numero_0, no sería correcto con un valor de “2”, pero es más fácil, cambiar de $numero_0, por $numero_2, en todo el texto. Porque si tienes que hacer este cambio es más fácil de esta forma, que cambiar 0 por 2, porque te chutaría el 100, 10, 50, 60, y esos no los quieres cambiar, esa es mi razón.

Las líneas 8 y 9 de select_db2 definen la misma variable, así que eso me dice que no estás usando

use strict;

y sospecho de que tampoco tienes activado

use warnings;
La variable de la línea 8 que se define, no me interesa qué valor pueda tomar, por la plancho en la línea 9.

En serio: los necesitas. Perl es tu mejor amigo a la hora de programar. Él mismo te dirá dónde están los primeros errores. Quizás tengas que escribir más my(), pero el programa quedará muy sólido.
Estoy utilizando variable globales, como son las contantes entre ellas están todos los $numero_0, y se definen en una subrutina. Tendría que llamar como main::variable, y así no fue preparado el programa, para los próximos programas lo tomaré en cuenta. Este programa está arriba de 20 000 líneas.

El error grave está en el paso de $sth entre las funciones.

En la línea 44 de select_db2() dice
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting

my $datos="$status|$sth";


Esa línea está interpolando las variables $status y $sth en cadena de caracteres. No hay problema con $status, porque contiene un valor escalar, pero $sth es un objeto, por lo que su interpolación será la versión texto del objeto. Por eso sale en pantalla "DBI::st=HASH(0xa27cea0)".
¿Al momento que se guarda en una cadena las variables en el caso de dbi, cambia su valor? Si la respuesta es sí, quiere decir que es por eso sin revisar el programa, que al momento del select, no encuentra nada, muy independientemente que los datos de la búsqueda estén bien.

¡Pero vuelvo a preguntar!

Cuando no se encuentran registros en el select, los inserta, de lo que en memoria tiene, ¿Porqué, en el insert sí funciona?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub insert_mundo
  2. {
  3.         print "$year/$mon/$mday:$hour:$min:insert_mundo entra \n";
  4.         my $dbh=$_[$numero_0];
  5.         my $table=$_[$numero_1];
  6.         my $indicador=$_[$numero_2];
  7.  
  8.         &verifica_campos;
  9.  
  10.         my $datos="\"$DB2_Mundo\",$DB2_Numero_Pueblos,$indicador,$DB2_Monedas,$DB2_Monedas_Generadas";
  11.         my $status=&insert_db2($dbh,$table,$datos);
  12.  
  13.         return($status);
  14. }
  15.  
  16. sub insert_db2
  17. {
  18.         print "$year/$mon/$mday:$hour:$min:insert_db2 entra \n";
  19.         my $dbh=$_[$numero_0];
  20.         my $table=$_[$numero_1];
  21.         my $datos=$_[$numero_2];
  22.  
  23.         my $comando_insert="insert into $table values($datos);";
  24.         print "################################################################\n";
  25.         print "$comando_insert\n";
  26.         print "################################################################\n";
  27.         my $db="$comando_insert";
  28.         my $sth = $dbh->prepare("$db") || die "$DBI::errstr";
  29.         my $status=$sth->execute();
  30.         if(!defined $status)
  31.         {
  32.                 print "################################################################\n";
  33.                 print "$year/$mon/$mday:$hour:$min:$table:ERROR:$DBI::errstr \n";
  34.                 print "################################################################\n";
  35.                 $status=$numero_1;
  36.                 exit;
  37.         }
  38.         else
  39.         {
  40.                 $status=$numero_0;
  41.         }
  42.  
  43.         return($status);
  44. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


No sé cómo será select_puntos(), pero me da la sensación de que tendrá las mismas líneas que select_db2(), porque, al llegar a la línea 20 de imprime_mundo(),
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting

my $datos=&select_puntos($dbh,$table,$llave,$numero_1);
my ($status,$sth)=split(/\|/,$datos);
if($status==$numero_0)
{
&imprime_puntos($sth,$table);
La subrutina select_puntos solo varía en la cantidad de datos de la tabla select_mundo, pero para seleccionar de acuerdo a la llave, utiliza una sola rutina que es select_db2.

La línea 20 está recibiendo unos $datos desde select_puntos(), que según la línea 21, se trata de una cadena de caracteres. Esa cadena la partes con split() en la línea 21, y dejas el resultado en $status y $sth. En ese momento, esas variables siguen conteniendo cadenas de caracteres. Aunque la variable se llame $sth no significa que contenga un objeto DBI. Sólo es una cadena de caracteres.

No sé lo que hace imprime_puntos(), pero si ese método cree que $sth es un objeto DBI, se equivoca completamente.

El error es ese: pasar entre funciones la conversión a texto de un objeto DBI.

El código es un poco... lioso... Le faltan buenas técnicas de programación. Por ejemplo: cuando el programa se hace muy grande, es muy peligroso confiar en las variables globales. Y las variables locales con my() tienen su vida limitada al contexto donde se declaran. Por eso es importante trabajar bien con los argumentos que se pasan a las funciones.

Una cosa más: si quieres tener un sistema profesional de registrado, te recomiendo Log-Log4perl. Te abreviará mucho el código de logging.
Dame una idea de cómo pasar un objeto la variable $dbh y $sth, a las subrutinas.

O cómo regresar su valor por ejemplo al select, y después para el imprime. O estas dos variable lo más correcto sería convertirlas en globales. Porque, si es así como lo dices y como lo entiendo, es que ese el el problema de todo.
Última edición por explorer el 2012-09-03 05:00 @250, editado 1 vez en total
Razón: Ajustar marcas de citas, y cambiado el orden de las respuestas
marcoamoncada
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2011-06-06 22:41 @986

Re: Tengo un problema cuando ejecuto el comando execute

Notapor explorer » 2012-09-03 07:45 @365

marcoamoncada escribiste:No soy muy afán a utilizar muchas constantes como sería preguntar por 0, o preguntar por “******algún texto******” porque, cuando tienes que cambiar por alguna razón, cambias en todo el texto, como por ejemplo preguntar por 10. Y ahora vas a preguntar por 20, solamente así cambias una variable no tienes que revisar todo el código. Claro, los nombre de $numero_0, no sería correcto con un valor de “2”, pero es más fácil, cambiar de $numero_0, por $numero_2, en todo el texto. Porque si tienes que hacer este cambio es más fácil de esta forma, que cambiar 0 por 2, porque te chutaría el 100, 10, 50, 60, y esos no los quieres cambiar, esa es mi razón.
Es cierto que suele ser mejor usar variables que constantes, cuando
  • el número de veces que aparece la constante es muy grande, y
  • la constante podría cambiar en una futura revisión del programa, y
  • la longitud de la variable que contiene el valor de la constante es menor que el de la propia constante
Un ejemplo clásico de la informática es declarar la constante
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $PI = 3.1415926535;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
al principio del programa. No porque un día vaya a cambiar el valor de π (que no lo va a hacer, desde luego), sino porque escribir $PI es más cómodo que escribir 3.1415926535.

Ahora bien, hay constantes y constantes. Y una de las constantes que jamás va a cambiar son los índices del array @_ que recibe los argumentos en las subrutinas. Así, el primer argumento siempre estará en $_[0], el segundo en $_[1], el tercero en $_[2], y así.

Entonces, funciones como
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub insert_db2 {
  2.     print "$year/$mon/$mday:$hour:$min:insert_db2 entra \n";
  3.     my $dbh=$_[$numero_0];
  4.     my $table=$_[$numero_1];
  5.     my $datos=$_[$numero_2];
  6.     ...;
  7. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
se pueden escribir mejor así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub insert_db2 {
  2.     print "$year/$mon/$mday:$hour:$min:insert_db2 entra \n";
  3.  
  4.     my $dbh   = $_[0];
  5.     my $table = $_[1];
  6.     my $datos = $_[2];
  7.  
  8.     ...;
  9. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
ya que siempre van a llegar los argumentos en las primeras posiciones de @_. O incluso mejor así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub insert_db2 {
  2.     print "$year/$mon/$mday:$hour:$min:insert_db2 entra \n";
  3.  
  4.     my($dbh, $table, $datos) = @_;
  5.  
  6.     ...;
  7. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


marcoamoncada escribiste:Estoy utilizando variable globales, como son las contantes entre ellas están todos los $numero_0, y se definen en una subrutina. Tendría que llamar como main::variable, y así no fue preparado el programa, para los próximos programas lo tomaré en cuenta. Este programa está arriba de 20 000 líneas.
Una norma de estilo puede ser:
  • escribir en mayúsculas la variable que contiene un valor constante que nunca cambia. Ejemplo: $PI
  • escribir en notación Camel las variables que pasan valores globales. Ejemplo: $Dbi
  • el resto, en minúsculas

marcoamoncada escribiste:¿Al momento que se guarda en una cadena las variables en el caso de dbi, cambia su valor? Si la respuesta es sí, quiere decir que es por eso sin revisar el programa, que al momento del select, no encuentra nada, muy independientemente que los datos de la búsqueda estén bien.
Sí... bueno, no exactamente... a ver con un ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $dbh
  2.     =  DBI->connect("DBI:mysql:$al;host=$am", $ak, $an)
  3.     or die "Could not connect to database:$DBI::errstr"
  4.     ;
  5. # aquí, $dbh es una variable escalar que almacena un objeto DBI
  6.  
  7. my $datos = "$status|$dbh";      # aquí, $datos contiene una cadena de caracteres,
  8.                                  # que son la interpolación a texto de los contenidos de las variables
  9.                                  # escalares $status y $dbh, unidas por el carácter '|'
  10.  
  11. # aquí, $dbh sigue conteniendo un objeto DBI
  12.  
  13. return $datos;                   # lo que estamos devolviendo es una cadena de textos,
  14.                                  # algo así: 1|DBI::st=HASH(0xa27cea0)
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Entonces, lo que recibe el programa a través del return() no es un objeto DBI, sino la representación texto de ese objeto DBI. Y con esa representación no puede hacer nada, no puede ejecutar ningún método DBI.

marcoamoncada escribiste:Cuando no se encuentran registros en el select, los inserta, de lo que en memoria tiene, ¿Porqué, en el insert sí funciona?
Pues porque en la línea 11 de insert_mundo() sí estás pasando el valor del objeto DBI. Estás pasando la variable $dbh tal cual, sin haber sido convertida a cadena de texto.

marcoamoncada escribiste:Dame una idea de cómo pasar un objeto la variable $dbh y $sth, a las subrutinas.

O cómo regresar su valor por ejemplo al select, y después para el imprime. O estas dos variable lo más correcto sería convertirlas en globales. Porque, si es así como lo dices y como lo entiendo, es que ese el el problema de todo.
Lo tienes hecho con el ejemplo de insert_mundo/insert_db2. Sería algo así:

En select_db2. En vez de
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     my $datos = "$status|$sth";
  2.     print "$datos \n";
  3.  
  4.     return ($datos);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
sería así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     return $status, $sth;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Y en select_mundo, en lugar de
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     my $status=&select_db2($dbh,$table,$where);
  2.     print "$status \n";
  3.     return($status);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
sería así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     my($status, $sth) = select_db2($dbh, $table, $where);
  2.     return $status, $sth;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Y ya solo queda recuperar los valores, en
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     my($status,$sth) = select_puntos($dbh, $table, $llave, $numero_1);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Es decir, vamos moviendo el contenido de $status y $sth de forma separada. Cada una va guardando su propio valor. Y manteniendo el sentido de ese valor: una es una cadena de texto y la otra almacena un objeto DBI.

Mira como se puede simplificar el código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use feature 'say';
  2.  
  3. my $DEBUG   = 1;
  4. my $__SEP__ = '#' x 80;
  5.  
  6. sub tick_time {
  7.     return "$year/$mon/$mday:$hour:$min";
  8. }
  9.  
  10. sub tick_log_time {
  11.     my $texto = shift;
  12.     return tick_time . ":$texto";
  13. }
  14.  
  15. sub tick_log_sep {
  16.     my $texto = shift;
  17.     return "$__SEP__\n$texto\n$__SEP__";
  18. }
  19.  
  20. sub insert_db2 {
  21.     say tick_log_time('insert_db2 entra')                             if $DEBUG;
  22.  
  23.     my($dbh, $table, $datos) = @_;
  24.  
  25.     my $comando_insert = "INSERT INTO $table values($datos)";
  26.     say tick_log_sep($comando_insert)                                 if $DEBUG;
  27.  
  28.     my $sth    = $dbh->prepare($comando_insert) or die "ERROR: $DBI::errstr";
  29.     my $status = $sth->execute();
  30.  
  31.     if (not defined $status) {
  32.         say tick_log_sep(tick_time . ":$table:ERROR:$DBI::errstr")    if $DEBUG;
  33.         return 0;
  34.     }
  35.     else {
  36.         return 1;
  37.     }
  38. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Nota: he puesto un return(0) al final, para marcar error, porque en Perl, equivale a falso, indicando que hubo un error en la ejecución de insert_db2.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14477
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Tengo un problema cuando ejecuto el comando execute

Notapor marcoamoncada » 2012-09-08 15:08 @672

Ya corregí lo más que pude, ¿por qué?

La inicialización de las variables se hace en una rutina. Y esa rutina se hace al inicio, ya nunca más se efectúa nuevamente, pero ahora me está reportando que unas variables no están inicializadas, te presento los ejemplos:

Ya codifiqué los parámetros, me llevo algo de tiempo por qué. El programa es grande, como lo comenté.
Sintáxis: [ Descargar ] [ Ocultar ]
  1. use strict; 
  2. use warnings; 


Este aviso lo manda porque está en varias líneas.
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Useless use of anonymous list ([]) in void context at /home/mr...pl line 724. 


Ya le cambié para que no metiera los objetos en string
Sintáxis: [ Descargar ] [ Ocultar ]
  1. my $dbh=&inicia; 
  2. &proceso($datos,$dbh); 
  3. sub inicia 
  4.     print &obten_tiempo_actual($main::NUMERO_1,"inicia"); 
  5.      
  6.     my $dbh=&conecta_db2; 
  7.     &variables_constantes; 


No puedes sortear algo no es numérico
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Useless use of sort in void context at /home/mr...pl line 1532. 
  2. 1532 
  3.     sort(@main::niveles_porcentaje); 


Sintáxis: [ Descargar ] [ Ocultar ]
  1.     my @a = @raw_firmarse; 
  2.     my @b = sort @a; 
  3. 1757    @raw_firmarse = sort {$b<=>$a} @a; 


La línea de sort() me reporta
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
  2. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
  3. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
  4. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
marcoamoncada
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2011-06-06 22:41 @986

Re: Tengo un problema cuando ejecuto el comando execute

Notapor explorer » 2012-09-08 22:40 @986

marcoamoncada escribiste:Este aviso lo manda porque está en varias líneas.
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Useless use of anonymous list ([]) in void context at /home/mr...pl line 724. 
Dice que hay un array anónimo que no está asignado a ninguna variable ni es devuelto por ninguna función, en esa línea.

marcoamoncada escribiste:No puedes sortear algo no es numérico
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Useless use of sort in void context at /home/mr...pl line 1532. 
  2. 1532 
  3.     sort(@main::niveles_porcentaje); 
El error dice que están mandando ordenar un array pero no has dicho dónde dejar el resultado de la ordenación.

marcoamoncada escribiste:La línea de sort() me reporta
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
  2. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
  3. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
  4. Argument "1|http://ww..." isn't numeric in sort at /home/mr...pl line 1757. 
En efecto: no son valores numéricos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14477
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 10 invitados