Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » PostgreSQL »

Problemas con el manejo de comillas en PL/pgSQL

Estas en el tema de Problemas con el manejo de comillas en PL/pgSQL en el foro de PostgreSQL en Foros del Web. Buenos dias, esta es mi duda: tengo un procedimiento almacenado que ejecuta una consulta como esta: select p.nombre_pais, r.nombre, c.nombre, l.nom_localidad, m.nivsocio, count(m.id) as total ...
  #1 (permalink)  
Antiguo 27/10/2009, 08:19
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
Exclamación Problemas con el manejo de comillas en PL/pgSQL

Buenos dias, esta es mi duda:

tengo un procedimiento almacenado que ejecuta una consulta como esta:

select p.nombre_pais,
r.nombre,
c.nombre,
l.nom_localidad,
m.nivsocio,
count(m.id) as total
from servcon_manzanas m

INNER JOIN servcon_localidades l ON (m.coddane = l.cod_dane AND m.localidad = l.cod_localidad AND l.cod_localidad IN ('11','01','02','04','06','8','12','13','15'))
INNER JOIN ciudades c ON (m.coddane = c.coddane)
INNER JOIN servcon_regiones r ON (m.codregion = r.cod_region)
INNER JOIN servcon_paises p ON (m.codpais = p.codigo)

where m.coddane = '11001' and
m.localidad IN ('11','01','02','04','06','8','12','13','15') and
m.nivsocio in ('3','2','6','4','5')
group by l.nom_localidad, m.nivsocio,c.nombre,r.nombre,p.nombre_pais
order by m.nivsocio,l.nom_localidad.

Pero los valores de filtro para:

l.cod_localidad IN ('11','01','02','04','06','8','12','13','15')
m.nivsocio in ('3','2','6','4','5')
m.coddane = '11001'

No se como enviarlos como parametro cuando invoco el procedimiento, y tampoco se como colocarlos en el codigo del procedimiento al cual llamo asi:

select * from p_blocks('"11","01","02","04","06","82,"12","13","15"','"2","3","2","6","4","5"','11001')
y no genera error, el query dentro del procedimiento lo cree asi y no genero error tampoco, pero al invocar el procedimiento no genera resultados y estoy esperando 27 filas.

--DEFINICION DE LA CONSULTA DENTRO DE p_blocks
select p.nombre_pais,
r.nombre AS region,
c.nombre AS ciudad,
l.nom_localidad,
m.nivsocio,
count(m.id) as total
from servcon_manzanas m

INNER JOIN servcon_localidades l ON (m.coddane = l.cod_dane AND m.localidad = l.cod_localidad AND l.cod_localidad IN ($1))
INNER JOIN ciudades c ON (m.coddane = c.coddane)
INNER JOIN servcon_regiones r ON (m.codregion = r.cod_region)
INNER JOIN servcon_paises p ON (m.codpais = p.codigo)

where m.coddane = $3 and
m.localidad IN ($1) and
m.nivsocio in ($2)
group by l.nom_localidad, m.nivsocio,c.nombre,r.nombre,p.nombre_pais
order by m.nivsocio,l.nom_localidad

LOOP RETURN NEXT query_result;
END LOOP;

alguien sabe como solucionar el problema
  #2 (permalink)  
Antiguo 27/10/2009, 08:45
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

Que tal webness
postea el procedimiento completo.
También la forma como lo ejecutas.

saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #3 (permalink)  
Antiguo 27/10/2009, 08:51
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

CREATE OR REPLACE FUNCTION p_blocks(varchar, varchar,varchar) RETURNS SETOF type_block AS $BODY$
DECLARE
query_result type_block;

BEGIN
FOR query_result IN
select p.nombre_pais,
r.nombre AS region,
c.nombre AS ciudad,
l.nom_localidad,
m.nivsocio,
count(m.id) as total
from servcon_manzanas m

INNER JOIN servcon_localidades l ON (m.coddane = l.cod_dane AND m.localidad = l.cod_localidad AND l.cod_localidad IN ($1))
INNER JOIN ciudades c ON (m.coddane = c.coddane)
INNER JOIN servcon_regiones r ON (m.codregion = r.cod_region)
INNER JOIN servcon_paises p ON (m.codpais = p.codigo)

where m.coddane = $3 and
m.localidad IN ($1) and
m.nivsocio in ($2)
group by l.nom_localidad, m.nivsocio,c.nombre,r.nombre,p.nombre_pais
order by m.nivsocio,l.nom_localidad

LOOP RETURN NEXT query_result;
END LOOP;

return;
END $BODY$
LANGUAGE plpgsql;


lo llamo asi:
$db->execute("select * from p_blocks(' ''11","01","02","04","06","8","12","13","15" ', ' "2",''3","2","6","4","5",'11001')");
  #4 (permalink)  
Antiguo 27/10/2009, 09:17
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

que es type_block?
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #5 (permalink)  
Antiguo 27/10/2009, 09:30
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

Es un tipo que cree para poder retornar el resultado del query, puesto que estoy sacando datos de varias tablas, eso creo que no tiene problema pues si ejecuto el SP con los datos quemados funciona correctamente
  #6 (permalink)  
Antiguo 27/10/2009, 18:18
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

ya entendí el problema.
te pongo un ejemplo para que veas como funciona

Código sql:
Ver original
  1. pruebas=> SELECT *FROM medico;
  2.  id | nombre
  3. ----+---------
  4.   1 | daniel
  5.   2 | daniela
  6.   3 | ana
  7. (3 filas)
  8.  
  9. pruebas=> CREATE OR REPLACE FUNCTION inf_concepto_nombre(nombre text)
  10. pruebas->   RETURNS SETOF medico AS
  11. pruebas-> $BODY$
  12. pruebas$> DECLARE
  13. pruebas$>
  14. pruebas$> fila medico%rowtype;
  15. pruebas$> SQL text;
  16. pruebas$> BEGIN
  17. pruebas$> SQL = 'select id,nombre FROM medico where nombre in(' || nombre || ')'
  18. ;
  19. pruebas$>
  20. pruebas$> FOR fila IN EXECUTE SQL
  21. pruebas$> LOOP
  22. pruebas$> RETURN NEXT fila;
  23. pruebas$> END LOOP;
  24. pruebas$> RETURN;
  25. pruebas$> END;
  26. pruebas$> $BODY$
  27. pruebas->   LANGUAGE 'plpgsql' VOLATILE;
  28. CREATE FUNCTION
  29. pruebas=> SELECT *FROM inf_concepto_nombre($$'daniel','ana'$$);
  30.  id | nombre
  31. ----+--------
  32.   1 | daniel
  33.   3 | ana
  34. (2 filas)
  35.  
  36. pruebas=>

El el llamado de la función se puede valer de $$ para poder ingresar las comillas (') como parte de la cadena.

Nos cuentas como te va
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #7 (permalink)  
Antiguo 28/10/2009, 08:47
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

BUENO TRANSFORME MI PROCEDEMIENTO ALMACENADO A ESTO:

CREATE OR REPLACE FUNCTION p_get_blocks_count_co(integer, varchar,varchar,varchar) RETURNS SETOF type_block AS $BODY$
DECLARE
filter ALIAS FOR $1;
locales ALIAS FOR $2;
city ALIAS FOR $3;
socioeconomic ALIAS FOR $4;
query_result type_block;
BEGIN
IF filter = 1 THEN
FOR query_result IN
SELECT *
FROM conteo_manzanas_localidad_co
WHERE locale_code IN (' | locales | ') AND
city_code = ' | city | ' AND
socioeconomic_status IN (' | socioeconomic | ')

LOOP RETURN NEXT query_result;
END LOOP;
ELSE
FOR query_result IN
SELECT *
FROM conteo_manzanas_barrios_co
WHERE locale_code IN (' | locales | ') AND
city_code = ' | city | ' AND
socioeconomic_status IN (' | socioeconomic | ')

LOOP RETURN NEXT query_result;
END LOOP;
END IF;
RETURN;
END $BODY$
LANGUAGE plpgsql;


Y EL LLAMADO LO ESTOY HACIENDO DE ESTA FORMA:

SELECT *
FROM get_blocks_count_co(1,$$'11','01','02','04','06',' 8','12','13','15'$$,'11001',$$'3','2','6','4','5'$ $)


PERO ME GENERA EL SIGUIENTE ERROR:

Error de SQL:

ERROR: function get_blocks_count_co(integer, "unknown", "unknown", "unknown") does not exist
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
  #8 (permalink)  
Antiguo 28/10/2009, 09:03
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

Upsss, no me habia fijado estaba llamando mal al procedimiento, ya no genera error pero no me esta devolviendo resultados
  #9 (permalink)  
Antiguo 28/10/2009, 09:07
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

la concatenación la haces con un solo |
Tengo entendido que debe ser con ||.

ahora bien, si no estas ejecutando una variable, no veo la necesidad de concatenar la consulta si la ejecutas directamente dentro del for.

Los errores que te muestra, puedes ensayar varias cosas:
Cita:
ERROR: function get_blocks_count_co(integer, "unknown", "unknown", "unknown") does not exist
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
No está reconociendo los 3 ultimos parametros, así que puedes hyudar a la función haciendo los respectivos parseos.
Código sql:
Ver original
  1. SELECT  *
  2. FROM get_blocks_count_co(1,$$'11','01','02','04','06',' 8','12','13','15'$$::VARCHAR,'11001'::VARCHAR,$$'3','2','6','4','5'$$::VARCHAR)

Te recomiendo hacer pruebas sencillas para detectar facilmente donde se presentan los errores. Prueba primero con una consulta simple sin variables de entrada, sino con los datos dentro de la función y asegurate donde detectar los errores
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #10 (permalink)  
Antiguo 28/10/2009, 09:55
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

como hago para insertar los bloques de codigo:

Cambie el SP quitandole las variables y dejandole los datos quemados, y cuando lo llamo le hice el parseo que me sugeriste y me da los resultados esperados, pero necesito obviamente que estos valores sean dinamicos.
  #11 (permalink)  
Antiguo 28/10/2009, 10:20
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

fijate en el ejemplo que te pasé en el 6to post.

La variable nombre es la de entrada y se ubica en el in de la consulta.
Vos tenés un ejemplo complejo y como no tengo ni el tipo de dato que utilizas (me imagino que lo creaste con create type) ni las tablas relacionadas en la consulta.

El secreto de todo es realizar pruebas de que retorna cada parte de la función.

Yo siempre me creo una pequeña función que me retorne toda la cadena del select para tener claro que no me estoy equivocando en ninguna concatenación. De ahí en adelante, debes detectar que devuelve cada operación del procedimiento e ir corrigiendo las inconsistencias.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #12 (permalink)  
Antiguo 28/10/2009, 10:53
Avatar de webness  
Fecha de Ingreso: enero-2009
Ubicación: BOGOTA
Mensajes: 312
Antigüedad: 15 años, 3 meses
Puntos: 5
De acuerdo Respuesta: Problemas con el manejo de comillas en PL/pgSQL

Bueno, muchas gracias por tu ayuda, creo al final de cuentas mi error era que no lei a cabalidad tu ejemplo: El resultado final fue:

Código PHP:
CREATE OR REPLACE FUNCTION p_get_blocks_count(integervarchar,varchar,varchar,varcharRETURNS SETOF type_block_count AS $BODY$
DECLARE 
    
filter    ALIAS FOR $1;  
    list    
ALIAS FOR $2;
    
city      ALIAS FOR $3;
    
socioeconomic    ALIAS FOR $4;
    
country ALIAS FOR $5;
    
    
sql_query varchar;
    
query_result type_block_count;
BEGIN
    
IF filter 1 THEN
        sql_query 
:= 'SELECT    *
                       FROM    conteo_manzanas_localidad_'
||country||'
                       WHERE   locale_code IN ('
||list||') AND 
                               city_code = '
||city||' AND
                               socioeconomic_status IN ('
||socioeconomic||')';
        FOR 
query_result IN EXECUTE sql_query LOOP RETURN NEXT query_result;
        
END LOOP;            
    ELSE
        
sql_query := 'SELECT    *
                       FROM    conteo_manzanas_barrios_'
||country||'
                       WHERE   locale_code IN ('
||list||') AND 
                               city_code = '
||city||' AND
                               socioeconomic_status IN ('
||socioeconomic||')';
        FOR 
query_result IN EXECUTE sql_query LOOP RETURN NEXT query_result;
        
END LOOP;                
        
END IF;
    RETURN;
END $BODY$
LANGUAGE plpgsql
EL LLAMADO FINAL A LA FUNCION FUE:

Código PHP:
SELECT    *
FROM     p_get_blocks_count(1,$$'11','01','02','04','06','8','12','13','15'$$::varchar,'11001',$$'3','2','6','4','5'$$::varchar,'co'
Y EL TIPO QUE CREE FUE ESTE:

Código PHP:
 CREATE TYPE type_block_count AS
(
country_name varchar,
region_name varchar,
city_name varchar,
locale_name varchar,
locale_code varchar,
socioeconomic_status varchar,
city_code varchar,
total integer
MUCHAS GRACIAS POR TUS APORTES APRENDI BASTANTE.
  #13 (permalink)  
Antiguo 28/10/2009, 10:58
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problemas con el manejo de comillas en PL/pgSQL

De nada
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:57.