2011-10-04 16 views
5

Esto puede ser una pregunta para principiantes, pero quiero evitar el desbordamiento del búfer. Leí muchos datos del registro que se cargarán en una base de datos SQL. Leí los datos en un bucle, y los datos se insertaron después de cada ciclo. Mi problema es que de esta manera, si leo 20 claves y los valores debajo de (el número de teclas es diferente en cada computadora), entonces tengo que conectarme a la base de datos SQL 20 veces.¿Cómo manejar una cadena enorme correctamente?

Sin embargo, descubrí que hay una manera de crear un procedimiento almacenado y pasar todos los datos, por lo que el servidor SQL tratará con los datos, y tengo que conectarme solo una vez al servidor SQL .

Desafortunadamente no sé cómo manejar una cadena tan grande para evitar errores inesperados, como el buffer owerflow. Entonces mi pregunta es ¿cómo debo declarar esta cadena?

¿Debo hacer una cadena como char string[ 15000 ]; y concatenar los valores? ¿O hay una manera más simple de hacer esto?

Gracias!

+6

sería de gran ayuda si sabíamos que el lenguaje de programación que está utilizando, C o C++ –

+0

@ Rob:. estoy usando C, pero si alguien muestra un ejemplo de un C++, entonces puedo usarlo también – kampi

+4

no ¿Por qué sólo hacer múltiples consultas de inserción con una conexión? – Dmitri

Respuesta

2

Las cadenas STL deberían hacer un trabajo mucho mejor que el enfoque que ha descrito.

También deberá crear algunos umbrales. Por ejemplo, si su cadena creció más de un megabyte, valdría la pena considerar hacer diferentes conexiones SQL ya que su transacción será demasiado larga.

+1

También tenga en cuenta que las cadenas de bibliotecas estándar de C++ son solo C++, no C. La biblioteca que viene con implementaciones C++ es la biblioteca C++ estándar, _no_ el STL. –

+0

Mooing Duck: potàto de patata, al menos en este caso ('std :: string'). 'STL' todavía se puede usar sin ambigüedades para referirse a esa parte de la biblioteca estándar de C++ que originalmente se conocía como STL y luego se incorporó a la biblioteca estándar. – rubenvb

0

Para hacer esto correctamente en C, necesita asignar la memoria dinámicamente, utilizando malloc o uno de los equivalentes del sistema operativo. La idea aquí es averiguar cuánta memoria realmente necesita y luego asignar la cantidad correcta. Las funciones de registro proporcionan varias formas de determinar la cantidad de memoria que necesita para cada lectura.

Se pone un poco más complicado si está leyendo múltiples valores y concatenándolos. Un enfoque sería leer cada valor en un bloque de memoria asignado por separado, luego concatenarlos a un nuevo bloque de memoria una vez que los tenga todos.

Sin embargo, puede que no sea necesario tomarse tantas molestias. Si puede decir "si los datos son más de X bytes, el programa fallará", entonces puede simplemente crear un búfer estático como sugiere. Solo asegúrese de proporcionar las funciones de concatenación de cadenas y registro con el tamaño correcto para la parte restante del búfer y compruebe si hay errores, de modo que si falla, falla correctamente en lugar de bloquearse.

Una nota más: char buf[15000]; está bien siempre que la declaración esté dentro del alcance del programa, pero si aparece en una función, debe agregar el especificador static. La memoria asignada implícitamente en una función se toma por defecto de la pila, por lo que es probable que una asignación grande falle y bloquee su programa. (Quince mil bytes debería estar bien, pero no es un buen hábito para entrar.)

Además, es preferible definir una macro para el tamaño de su memoria intermedia, y lo utilizan constantemente:

#define BUFFER_SIZE 15000 
char buf[BUFFER_SIZE]; 

para que pueda aumentar fácilmente el tamaño del búfer más adelante modificando una sola línea.

+0

He editado tu respuesta un poco. Los nombres de macro son convencionalmente mayúsculas, por lo que se destacan. Y 'string' no es un nombre muy bueno para un objeto; Lo cambié a 'buf'. –

+0

@Keith, utilicé la cuerda [] porque eso era lo que OP usaba en su pregunta, pero en realidad no importa. Gracias por capturar el nombre de la macro en minúsculas, debo haber estado medio dormido. –

0

Puede leer pares (clave, valor) de un registro y almacenarlos en un búfer preasignado mientras haya espacio suficiente allí. Mantenga la posición de "escritura" dentro del búfer. Puede usarlo para verificar si hay espacio suficiente para una nueva clave, par de valores en el búfer. Cuando no queda espacio para el nuevo par (clave, valor): ejecute el procedimiento almacenado y restablezca la posición de "escritura" dentro del búfer. Al final del ciclo "read key, value pairs" - verifique la posición de "escritura" del búfer y ejecute el procedimiento almacenado si es mayor que 0. De esta manera minimizará el número de veces que ejecuta el procedimiento almacenado en un servidor

const int MAX_BUFFER_SIZE = 15000; 
char buffer[MAX_BUFFER_SIZE]; 
char buffer_pos = 0; // "write" position within the buffer. 

... 

// Retrieve key, value pairs and push them into the buffer. 
while(get_next_key_value(key, value)) { 
    post(key, value); 
} 

// Execute stored procedure if buffer is not empty. 
if(buffer_pos > 0) { 
    exec_stored_procedure(buffer); 
} 
... 

bool post(const char* key, const char* value) 
{ 
    int len = strlen(key) + strlen(value) + <length of separators>; 

    // Execute stored procedure if there is no space for new key/value pair. 
    if(len + buffer_pos >= MAX_BUFFER_SIZE) { 
    exec_stored_procedure(buffer); 
    buffer_pos = 0; // Reset "write" position. 
    } 

    // Copy key, value pair to the buffer if there is sufficient space. 
    if(len + buffer_pos < MAX_BUFFER_SIZE) { 
    <copy key, value to the buffer, starting from "write" position> 
    buffer_pos += len; // Adjust "write" position. 
    return true; 
    } 
    else { 
    return false; 
    } 
} 

bool exec_stored_procedure(const char* buf) 
{ 
    <connect to SQL database and execute stored procedure.> 
} 
Cuestiones relacionadas