2012-09-07 25 views
6

estoy tirando direcciones URL de mi base de datos con un script Perl, donde yo empleo fetchrow_array para tirar URL de la base de datos que funcionaba bien hasta que me encontré con una dirección URL muy larga georgelog24.blog.iskreni.net/?bid=6744d9dcf85991ed2e4b8a258153a1ab&lid=ff9963b9a798ea335b75b5f7c0c295d1
entonces empezó a dame este errorbase de datos failed trunca largo DBI atributo

DBD::ODBC::st fetchrow_array failed: st_fetch/SQLFetch (long truncated DBI attribute LongTruncOk not set and/or LongReadLen too small) (SQL-HY000) [state was HY000 now 01004] 
[Microsoft][ODBC SQL Server Driver]String data, right truncation (SQL-01004) at C:\test\multihashtest2.pl line 44. 

Creo que esto está en el lado de la base de datos ya que el código que he estado utilizando para extraer URL ha funcionado antes. La base de datos que estoy usando es MSSQL Server 2005.

la columna de la dirección URL en la base de datos utiliza texto tipo actualmente, pero he intentado cambiar a varchar (max) y nvarchar (max) pero el error sigue en pie.

Después de un poco de prueba y error, encontré que la longitud máxima de la url que podía consultar con fetchrow_array era de 81 caracteres. Y dado que las URL pueden abarcar longitudes ridículas a veces, no puedo poner una restricción en la longitud de la URL.

¿Alguien puede ayudarme a entender y sugerir una solución para esto?

FYI: la línea 44 es la primera línea en mi código de abajo

while (($myid,$url) = $statement_handle->fetchrow_array()) { # executes as many threads as there are jobs to do 
    my $thread = threads->create(\&webcrawl); #initiate thread 
    my $tid = $thread->tid; 
    print " - Thread $tid started\n"; #obtain thread no. and print 
    push (@Threads, $thread); #push thread into array for "housekeeping" later on 
} 

Respuesta

5

favor, mire la DBI atributos LongTruncOk y LongReadlen

Tendrá que aceptar truncamiento o establecer un tamaño máximo como texto y las columnas varchar (max) pueden ser masivas, por lo que si se dejara en el DBD, no tendría más remedio que asignar cantidades masivas de memoria en caso de que la columna tenga el tamaño máximo de esa columna.

10

intento con:

#not anymore errors if content is truncated - you don't necessarily want this 
$statement_handle->{'LongTruncOk'} = 1; 

#nice, hard coded constant for the length of data to be read from Longs 
$statement_handle->{'LongReadLen'} = 20000; 
while (($myid,$url) = $statement_handle->fetchrow_array()) { # executes as many threads as there are jobs to do 
    my $thread = threads->create(\&webcrawl); #initiate thread 
    my $tid = $thread->tid; 
    print " - Thread $tid started\n"; #obtain thread no. and print 
    push (@Threads, $thread); #push thread into array for "housekeeping" later on 
} 

Además, me gustaría recomendar a probar Parallel::ForkManager para la paralelización de puestos de trabajo - Me resulta mucho más intuitiva y fácil de usar que los hilos

+0

Gracias por elaborar más sobre cómo aplicar LongReadLen. ForkManager parece más fácil que los hilos. Casi como si fuera un semáforo y un hilo combinados. –

+1

Por cierto, solo como una adición, http://search.cpan.org/~timb/DBI-1.622/DBI.pm#LongReadLen. Cambiar el valor de 'LongReadLen' para un identificador de sentencia después de haber sido' prepare''d normalmente no tendrá ningún efecto, por lo que es común establecer 'LongReadLen' en' $ dbh' antes de llamar a 'prepare'. – stenlytw

3

punto importante: que necesita establecer los atributos LongReadLen y/o LongTruncOk en el identificador de la base de datosantes de para preparar la instrucción, como se indica en here.

Intentar establecerlo en la instrucción preparada, manejar antes de recuperar datos no tendrá efecto en el truncamiento de los datos devueltos.

+0

Gracias. Esta es la solución para hacer que esto funcione. –

Cuestiones relacionadas