Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - ^Tifa^

#591
Vamos a ver lo que yo entiendo tu tienes 2 tablas por ejemplo, y tu quieres obtener los registros de 1 tabla pero que no aparezcan en la otra???? porque si fuera el caso seria algo asi:

Código (sql) [Seleccionar]


mysql> select * from prueba;
+----------+---------+
| numerito | datitos |
+----------+---------+
|        1 |       1 |
|        1 |       2 |
|        4 |       1 |
|        4 |       3 |
+----------+---------+
4 rows in set (0.00 sec)

mysql> select * from ejemplo;
+--------+-------+
| numero | datos |
+--------+-------+
|      1 |     1 |
|      2 |     2 |
|      3 |     3 |
|      4 |     4 |
|      5 |     5 |
+--------+-------+
5 rows in set (0.00 sec)


mysql> select ejemplo.numero from ejemplo where ejemplo.datos not in( select num
erito from prueba );
+--------+
| numero |
+--------+
|      2 |
|      3 |
|      5 |
+--------+
3 rows in set (0.02 sec)

#592
Tengo varios amigos webmasters que de vez en cuando suelen recurrir a preguntarme o solicitarme algun tipo de ayuda referente a optimizacion de consultas en el motor MySQL.

Resulta que en dias pasados, un amigo muy cercano me solicito ayuda debido a que el posee una tabla con los links URL de cada web en su proyecto, como son muchos URLs (miles de sublinks) que heredan de otros links, el tiene una primary key por cada link, pero puestos en el tema todos saben lo dificil que es recordarse o relacionar el valor que posee el primary key del link numero 2000 por ejemplo, por ende el utilizaba como indice el campo URL de su tabla. Pero dicho campo era varchar(100) lo cual solia relantelizar la respuestas del servidor a la hora de muchas consultas masivas de clickeos en links aun siendo dicho campo un indice.

Como su aplicacion corre en MySQL, y el unico motor de almacenamiento en MySQL que soporta hash indices es el motor MEMORY el cual solo guarda temporalmente en memoria los datos, y el usaba MyISAM, procedi a ofrecerle un pseudo hash indice en MYISAM.

Por ejemplo implemento la siguiente tabla:

Código (sql) [Seleccionar]


mysql> describe ejemplo;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | smallint(6)   | NO   | PRI | 0       |       |
| url   | varchar(50)   | YES  |     | NULL    |       |
| url_x | decimal(10,0) | YES  | MUL | NULL    |       |
+-------+---------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

mysql> insert into ejemplo values(5, 'www.google.com/index?234web%3%.asp', crc32('www.google.com/index?234web%3%.asp'));
Query OK, 1 row affected (0.00 sec)

mysql> insert into ejemplo values(6, 'www.amigos.com/amistad/indice/fotos/personas', crc32('www.amigos.com/amistad/indice/fotos/personas'));
Query OK, 1 row affected (0.00 sec)

mysql> select * from ejemplo;
+----+----------------------------------------------+------------+
| id | url                                          | url_x      |
+----+----------------------------------------------+------------+
|  4 | www.yahoo.com                                | 3748556277 |
|  3 | www.mysql.com                                | 2595849497 |
|  2 | www.google.com                               |  526628817 |
|  1 | www.google.com/index.php                     | 1007078110 |
|  5 | www.google.com/index?234web%3%.asp           | 4027181565 |
|  6 | www.amigos.com/amistad/indice/fotos/personas | 1498747455 |
+----+----------------------------------------------+------------+
6 rows in set (0.00 sec)



En lo anterior presento como quite el indice del campo URL que es VARCHAR, asigne un campo 'extra' llamado URL_X de tipo NUMERIC (Las consultas sobre indices constantes numericos son de mayor velocidad que en campos caracteres). y le declare un INDEX a este ultimo campo, dejando al campo ID como llave primaria y a URL_X como INDEX.

Ahora hago una ligera consulta:

Código (sql) [Seleccionar]


mysql> select url,id from ejemplo where url_x = crc32('www.yahoo.com') and id > 0;
+---------------+----+
| url           | id |
+---------------+----+
| www.yahoo.com |  4 |
+---------------+----+
1 row in set (0.00 sec)

mysql> select url,id from ejemplo where url_x = crc32('www.google.com/index?234web%3%.asp') and id > 0;
+------------------------------------+----+
| url                                | id |
+------------------------------------+----+
| www.google.com/index?234web%3%.asp |  5 |
+------------------------------------+----+
1 row in set (0.00 sec)



Diran que es pesado estar realizando puros INSERT repitiendo la URL en 2 campos a la vez siempre, por ende para manejar de manera automatica lo anterior se puede hacer un TRIGGER:

Código (sql) [Seleccionar]


mysql> delimiter ;
mysql> describe ejemplo;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | smallint(6)   | NO   | PRI | 0       |       |
| url   | varchar(50)   | YES  |     | NULL    |       |
| url_x | decimal(10,0) | YES  | MUL | NULL    |       |
+-------+---------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

mysql> insert into ejemplo(id,url) values(7,'www.gifmania.com/perros/chihuahua.jpg');
Query OK, 1 row affected (0.02 sec)

mysql> insert into ejemplo(id,url) values(8,'www.gifmania.com/perros/peluche.jpg');
Query OK, 1 row affected (0.00 sec)

mysql> insert into ejemplo(id,url) values(9,'www.gifmania.com/perros/pitbull.jpg');
Query OK, 1 row affected (0.00 sec)

mysql> select * from ejemplo;
+----+----------------------------------------------+------------+
| id | url                                          | url_x      |
+----+----------------------------------------------+------------+
|  4 | www.yahoo.com                                | 3748556277 |
|  3 | www.mysql.com                                | 2595849497 |
|  2 | www.google.com                               |  526628817 |
|  1 | www.google.com/index.php                     | 1007078110 |
|  5 | www.google.com/index?234web%3%.asp           | 4027181565 |
|  6 | www.amigos.com/amistad/indice/fotos/personas | 1498747455 |
|  7 | www.gifmania.com/perros/chihuahua.jpg        | 1056638155 |
|  8 | www.gifmania.com/perros/peluche.jpg          | 1463517104 |
|  9 | www.gifmania.com/perros/pitbull.jpg          | 3203321590 |
+----+----------------------------------------------+------------+
9 rows in set (0.00 sec)

mysql> select url,id from ejemplo where url_x = crc32('www.gifmania.com/perros/pitbull.jpg') and id > 0;
+-------------------------------------+----+
| url                                 | id |
+-------------------------------------+----+
| www.gifmania.com/perros/pitbull.jpg |  9 |
+-------------------------------------+----+
1 row in set (0.00 sec)




Tambien se puede implementar un TRIGGER update para las situaciones de actualizacion del campo URL. Ahora la mejor parte, analizar la consulta con EXPLAIN para ver el nivel de Optimizacion de la misma:

Código (sql) [Seleccionar]


mysql> explain select url,id from ejemplo where url_x = crc32('www.gifmania.com/perros/pitbull.jpg') and id > 0;
+----+-------------+---------+------+---------------+-------+---------+-------+------+-------------+
| id | select_type | table   | type | possible_keys | key   | key_len | ref   | rows | Extra       |
+----+-------------+---------+------+---------------+-------+---------+-------+------+-------------+
|  1 | SIMPLE      | ejemplo | ref  | PRIMARY,url_x | url_x | 6       | const |    1 | Using where |
+----+-------------+---------+------+---------------+-------+---------+-------+------+-------------+
1 row in set (0.00 sec)



Donde se ve claramente acorde al optimizador interno de MySQL, que se da uso del indice URL_X con un valor constante y se analiza sencillamente 1 sola fila de toda la tabla, el motor sabe exactamente ya donde ir, y para alcanzar su objetivo solamente analizo 1 fila.

Sin embargo si se aplica el EXPLAIN sobre el campo URL (Que es VARCHAR no tiene ningun indice asignado):

Código (sql) [Seleccionar]


mysql> explain select url,id from ejemplo where url = 'www.gifmania.com/perros/peluche.jpg'  and id > 0;
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | ejemplo | ALL  | PRIMARY       | NULL | NULL    | NULL |    9 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> notee;



Aca se ve que no aplica ningun indice, ni aprovecha ninguna llave ni nada analiza todas las filas existentes en mi tabla para retornarme el valor.

Diran que es mas factible asignar indice al campo URL y ya estuvo, pero por optimizacion las lecturas de un indice sobre valores de longitud dinamica donde puedo encontrar valores de 50 caracteres como de 20 caracteres en la proxima verificacion es algo que relantiza el proceso y provoca lo que mi amistad estaba padeciendo.

El tuvo que reconstruir su tabla, pero su proyecto va muchisimo mejor en respuesta de solicitudes, y ya que es una tecnica muy popular colocar urls en las tablas es preferible asignarle un pseudoindice que funcione como un hash indice que asignar dicho campo de longitud variable y de poca optimizacion.
#593
Scripting / Re: Quitar 1 expresion con SED
14 Diciembre 2009, 00:28 AM
Ya pude sacar algo y resolverlo... no es lo mas optimo pero funciona.

Todo era hacer:

Citar

extra='`';

sed "s/$extra/ /" $new > tmp && mv tmp $new
sed "s/$extra/ /" $new > tmp && mv tmp $new


AHora si ya me carga el script en Oracle  :P
#594
Scripting / Re: Quitar 1 expresion con SED
14 Diciembre 2009, 00:13 AM
No creo que cometas una burrada.

Si lamentablemente si habia probrado con comillas simples en vez de dobles en la variable $extra pero si utilizo comillas simples asi:

extra='`'

Resulta que SED se lleva la linea completa donde vea `

Quedando mi archivo copia (El que debo cargar en Oracle asi)

Citar-- Host: localhost    Database: primaria                       
-- ------------------------------------------------------       
-- Server version       5.4.3-beta                             
--                                                             
--                                                             
)                                                               
--                                                             
--                                                             
--                                                             
--                                                             
)             

Donde sea que encuentre un

Create table `copia`

me elimina la linea completa.... y ando dandole vueltas haber como decirle que no sea la linea completa, sino sencillamente la comilla inclinada ` para que quede normal

CREATE TABLE copia

en vez de

CREATE TABLE `copia`
#595
Scripting / Quitar 1 expresion con SED
13 Diciembre 2009, 23:01 PM
Hola.  :D

Estoy haciendo una migracion manual de un dumpeo de un esquema de MySQL hacia Oracle. (Se que puedo utilizar ETL gratuitos o Oracle Workbench) pero no es el caso, no hay servidor grafico y no puedo instalar muchas cosas raras en el PC que es.

Bien asi que la migracion que en este caso son sencillas (tablas nada de procedimientos, ni triggers ni funciones) he creado el siguiente script en bash que me serviria con una unica falla:

Código (perl) [Seleccionar]

#!/bin/bash -x

mensaje="UNLOCK TABLES*";
mensajito="LOCK TABLES*";
archivo="/home/marian/pepe/backup.sql";
mensaje1="*";
mensaje2="*";
mensaje3="ENGINE*";
new="/home/marian/pepe/nuevo.txt";
fin="NULL  ";
curva=")";
indices="KEY";
tabla="DROP TABLE*"
extra="``";

sed "/$mensaje/d"  $archivo > nuevo.txt
sed "/$mensajito/d" $new > tmp && mv tmp $new
sed "/$mensaje1/d" $new > tmp && mv tmp $new
sed "/$mensaje2/d" $new > tmp && mv tmp $new
sed "/$tabla/d" $new > tmp && mv tmp $new
sed "/$extra/d" $new > tmp && mv tmp $new
sed "s/$indices/UNIQUE/" $new > tmp && mv tmp $new
sed "/^$/d" $new > tmp && mv tmp $new
sed -e "/$mensaje3/G" $new > tmp && mv tmp $new
sed "/$mensaje3/d" $new > tmp && mv tmp $new
sed "s/^$/$curva/" $new > tmp && mv tmp $new



Mi falla es en la variable $extra="`" como bien saben la comilla inclinada (`) sirve para ejecucion, y no encuentro forma de quitarla con SED en el archivo generado por mysqldump:

Código (perl) [Seleccionar]


bash-3.1$ cat nuevo.txt                                         
-- MySQL dump 10.13  Distrib 5.4.3-beta, for pc-linux-gnu (i686)
--                                                             
-- Host: localhost    Database: primaria                       
-- ------------------------------------------------------       
-- Server version       5.4.3-beta                             
--                                                             
-- Table structure for table `copia`                           
--                                                             
CREATE TABLE `copia` (                                         
  `data` int(11) DEFAULT NULL,                                 
  `apellidos` char(20) DEFAULT NULL,                           
  UNIQUE `data` (`data`)                                       
)                                                               
--                                                             
-- Dumping data for table `copia`                               
--                                                             
INSERT INTO `copia` VALUES (1,'Lopez'),(2,'Sanchez'),(2,'Sanz'),(5,'Heredia'),(4,'Mendeira');
--                                             



Lo que la variable $extra en este caso me esta haciendo es eliminandome todas las lineas donde encuentre la dichosa comilla `valor` la linea completa  :-\  y yo solo quiero que por ejemplo a:

CREATE TABLE `copia`

me lo deje como

CREATE TABLE copia

lo unico que quiero eliminar es la comillita simple inclinada no el valor dentro de la misma.

Alguien sabe como puedo hacer eso con el comando SED en Linux?
#596
Bases de Datos / Re: IN() estricto...
13 Diciembre 2009, 22:16 PM
Yo no entiendo muy del todo tu solicitud, disculpa.

Hasta lo que he podido interpretar, me he imaginado que tienes 2 tablas una llamada colx la otra sencillamente x y que ambas tienen datos en comun pero que le falta a la otra y viceversa. Y segun creo tu quieres solicitar los datos de X campo en una tabla donde estos concuerden completamente con los de la tabla Y de lo contrario no se retorne ningun valor?

Por ejemplo si la tabla X tiene de campos (1,2,3) y la tabla Y tiene de campos (1,2,4) y yo hiciese SELECT * FROM X WHERE CAMPO IN(1,2,5)  no te retorne nada ya que los datos concuerdan en los valores 1 y 2 con la tbla Y pero no concuerdan con ningun 5.

Ten pendiente que los valores dentro de la funcion IN() es un rango de valores, no son valores constantes explicitos que indiquen que sino se cumplen todos retorne nada, aca es un rango si concuerdan 1 o 2 o mas se retornan estos el resto que no concuerde se obvia. (Creo que ya te diste cuenta de esto).

Entonces como la funcionalidad como tal de la funcion IN() no la puedes variar ni cambiar, tendras que hacer un rejuego de logica para llegar a tu objetivo, o hacerlo mediante un lenguaje de programacion o hacerlo mediante procedimientos almacenados. Pero suponiendo un ejemplo de tu peticion en lenguaje SQL:

Imagina un escenario de 2 tablas:

Código (sql) [Seleccionar]


mysql> select * from copia;
+------+-----------+       
| data | apellidos |       
+------+-----------+       
|    1 | Lopez     |       
|    2 | Sanchez   |       
|    2 | Sanz      |       
|    5 | Heredia   |       
|    4 | Mendeira  |       
+------+-----------+
5 rows in set (0.00 sec)

mysql> select * from ejemplo;
+-------+---------+
| datos | nombres |
+-------+---------+
|     1 | Maria   |
|     2 | Juan    |
|     2 | Raul    |
|     3 | Ruben   |
|     4 | Carlos  |
+-------+---------+
5 rows in set (0.00 sec)



Supongamos que yo quiero, todos los campos 'datos' de la tabla ejemplo que tenga un rango de numeros del 1,2 y un tercer numero que me servira de variable para mi busquedad  ;)

Código (sql) [Seleccionar]


mysql> select ejemplo.* from ejemplo inner join copia where copia.data = 4 and datos in(1,2,copia.data);
+-------+---------+
| datos | nombres |
+-------+---------+
|     1 | Maria   |
|     2 | Juan    |
|     2 | Raul    |
|     4 | Carlos  |
+-------+---------+
4 rows in set (0.00 sec)



En lo anterior el prefijo que mayormente se valida es el contenido de copia.data, los demas campos dentro de la funcion IN() '1 y 2' son constantes en este caso, y siempre se retornaran junto al tercer campo misterioso, siempre y cuando el tercer campo realmente exista en la tabla donde lo solicito. Por ende si existiera el numero 8 en el campo data de la tabla Copia, se va a retornar los valores unicos existentes '1 y 2' de la tabla ejemplo. Asi que mucho cuidado con esto, puesto que la validacion aca recae sobre la existencia del valor en la tablar Copia.

Ahora imaginate que hago una busquedad con un valor que Si existe en la tabla ejemplo, pero no existe en la tabla Copia:

Código (sql) [Seleccionar]


mysql> select ejemplo.* from ejemplo inner join copia where copia.data = 3 and datos in(1,2,copia.data);
Empty set (0.00 sec)

mysql> select * from ejemplo;
+-------+---------+
| datos | nombres |
+-------+---------+
|     1 | Maria   |
|     2 | Juan    |
|     2 | Raul    |
|     3 | Ruben   |
|     4 | Carlos  |
+-------+---------+
5 rows in set (0.00 sec)



El retorno es ninguno puesto que el valor 3 si existe en la tabla ejemplo, pero no existe en la tabla copia. Y aca el tercer campo misterioso que se le pasa a la funcion IN() es el valor que deseas buscar y que debe existir en realidad en la tabla copia, de lo contrario retorna nada.

Si juegas un poquito mas con la logica, podras implementar los 3 valores deseados dentro del IN() que se cumplan los 3 para retorno de valor o si falta alguno retorne nada.... todo es darle la vuelta a la logica del tema. O irse por el camino mas comodo pero un poco mas largo, 'programacion'
#597
No hay problema, cosas como estas pasan hasta a los genios  ;) 
#598
Una pregunta antes de proseguir.  Tienes en la cabecera de tus scripts 'perl' algo similar a esto:

#!C:\perl\bin

En la cabecera del script, tienes que poner la ruta exacta donde se encuentra el ejecutable perl.exe quedando el script mas o menos asi:

Código (perl) [Seleccionar]

#!C:\perl\bin
use strict;
use warnings;

my $tiempoe= time();
@files=<files/*>;

foreach $file (@files)
{
open(BHEX, "<$file");
my $buffer=<BHEX>;
close(BHEX);
open(BIN,">bin".$file.".bin")||die "No se puede crear el archivo bin".$file.".bin\n";
binmode(BIN);

foreach (split(" ", $buffer))
{
my $char=pack("H2",$_);
print BIN $char;
}
close(BIN);
}

my $tiempot = time()-$tiempoe;
print "Proceso Terminado\n";
print "Tiempo insumido: $tiempot seg.\n";







No tienes perl dentro del PATH general de Windows???? durante la instalacion con ActivePerl el te pregunta si quieres incluir PERL en el PATH general.. dijiste que si?

Porque es mas comodo sencillamente abrir un MS_DOS escribir perl y ya que incluir plenamente la ruta completa "C:\perl\bin\perl.exe" para ejecutar cualquier script *.pl

#599
Podrias obviar en este caso sqlite_error_string() y solamente utilizar sqlite_last_error() que te retorna el valor en numero del error SQLSTATE del motor, haz tratado algo como:

Código (php) [Seleccionar]


if ((sqlite_last_error($handle) == 4095 ) {

 echo "Error no existe la tabla seleccionada\n";

} elsif ((sqlite_last_error($handle)) == 4096 ) {

 echo "Error no tienes permiso de lectura en la tabla\n";

}



Donde 4095, 4096 son ejemplos de errores SQLSTATE del motor en cuestion... Ahora si solo te interesa imprimir el error de forma caracteres, no lo he hecho en PHP pero en Perl por ejemplo se haria asi:

Código (perl) [Seleccionar]


my $consulta = $conexión->prepare( qq{ SELECT * FROM tabla } );
$consulta->execute() or warn $conexión->errstr;



En lo anterior cuando se ejecuta la consulta si es efectivo obvia el warn sino es efectivo (Si no se cumple es false) entonces se ejecuta el $conexión->errstr y sale en pantalla el error que lanza el motor :

'Error table not found'  por ejemplo. No se como se haga en PHP esta situacion, pero no debe ir muy lejos. Haz intentado con:

Código (php) [Seleccionar]


$handle = sqlite_open('x.db', 0666);
$query = 'insert into xxx (id, data, nada) values (\'2\', \'WHK\', \'nono\')';
$data = sqlite_query($handle, $query) or die sqlite_error_string;

if ($data){
while($fila = sqlite_fetch_array($data, SQLITE_ASSOC)){
 $retorno[] = $fila;
}
print_r($retorno);
}



Sino aun tienes la opcion de las funciones almacenadas dentro del motor, no son tan dificiles  ;)  y suele ser hasta mas seguro para este tipo de aplicaciones.
#600
Querras descargarte el interprete desde ActivePerl (Perl para Windows)

http://www.activestate.com/activeperl/

Sobre compiladores de aplicaciones perl, he utilizado perlcc en Linux, y pues para Windows existe aunque no se si del todo gratuito perlAPP

Pero solo te serviria para crear aplicaciones o ejecutables de scripts perl, si aun estas interesado.