Ayuda con problema de claves primarias en tablas usando Power Builder

Oa friend necesito un ejemplo para entender mejor el tema de los errores.
Tengo la tabla ÁREA
-ARE_COD
-ARE_DESCRIPCION
Ambas primary key
Cuando estoy insertando un registro
Y ese registro ya esta en la tabla power da un error por defecto cierto.
O sea dice not unique key is duplica
Es necesario hacer la comparación en la tabla para ver si el dato ya esta o solo basta con manejar el error de otra forma ya que la llave no permite datos duplicados.
Me podrías dar un ejemplo en código de como solucionarías esto gracias amigo.

3 Respuestas

Respuesta
1
La llave primaria de la base de datos te garantiza que no se van a repetir datos. En la aplicación lo que debes hacer es validar para que si sale el error lo coloques bonito, y diga algo como "Dato incorrecto" o algo así.
Para eso en el datawindow busque el evento dberror y evalúa si el DBErrorCode(). No recuerdo cual es el código del error de llave primaria pero puede verlo así
long ll_Error_Nbr
ll_Error_Nbr = dw_1.DBErrorCode()
MessageBox("Database Error", "Number " + string(ll_Error_Nbr) , StopSign!)
Luego de saber cual es el error entonces en el evento dberror coloca
if codigodelerror = llaveduplicada then
messagebox("Error","llave duplicada")
end if
return 1
El return es para que no muestre el error de la base de datos por defecto.
Con esto solo vez el messagebox.
Respuesta
1
1. Una tabla con la estructura que planteas no necesita ambos campos como primary key
Si no querés que se duplique la descripción podes agregar una constraint unique por descripción
2. No tiene sentido hacer una comparación para ver si el registro ya existe en la base porque es una pérdida de tiempo y de procesamiento. Ese tipo de cosas se las dejás al DBMS que valida según la PORQUE o constraints que le hayas definido.
3. Si lo que querés es mostrar un mensaje de error personalizado (x ej: si el DBMS saca un error en ingles o con palabras raras para el usuario), lo que tenés que hacer es codificar el evento dberror() en la dw (te conviene en la estándar)
En el dberror capturá el número de error del DBMS y llamá a una fx que busque la correspondiente descripción en castellano en una tabla.
Ej: dberror
//sqldbcode = arg del evento
IF sqldbcode <> 0 THEN f_mensaje_error_detalle(sqldbcode)
//Si quieres podes preguntar que devuelve la fx y si da error o no encontró mostrar el mensaje original
return 1//para que no muestre el mensaje x defecto de PB
--------
f_mensaje_error_detalle(long arg)
//versión resumida
//acá haces un select de la tabla errores_bd_traducidos con el arg
//si no encuentra (sqlca.sqlcode = 100) entonces aún no lo traduciste, si queres podes generar un //log de mx pendientes y/o mostrar el mensajeoriginal si lo pasas como argumento return 0
//si error -> manejo de error return -1
//si lo encontró entonces
return messagebox("atención", "Ha ocurrido el siguiente error:~n" + ls_descipcion_de_la_tabla + "~nError número: " + String(arg)) //el error numerico se lo mostras para uqe lo pueda mencionar si llama al helpdesk o a alguien
Respuesta
1
Veo que sigues dándole duro al power.
En este caso, te voy a proponer un cambio de concepto muy sencillo y es el siguiente:
Si tienes una tabla con dos campos (código y descripción)
Lo normal sería que:
1º la primary key fuese solo la columna código.
2ºEse código no lo puede introducir el usuario, es decir, el campo tiene que estar o inhabilitado u oculto.
3º El campo código lo debes insertar tu (mediante código),
haciendo un "select max(are_cod) + 1 from area;"
Y luego hacer el setitem con el valor obtenido sobre el campo "are_cod" del datawindow.
3º Al usuario sólo le deberías dejar imputar la descripción (are_descripcion).
Esto es sencillo, ¿no? ¿No te parece mejor?
Bueno, en caso de que, "por historias de la vida" sea imprescindible utilizar la tabla tal y como me describes, la solución sería:
Cuando el usuario haya imputado ambos valores en los campos del tadawindow y pinche en actualizar puedes hacer dos cosas:
1ª.
Llamar a la función UPDATE del datawindow.
El error de clave duplicada de power builder(el que tu me comentas))
Puedes controlarlo en el evento del datawindow "db_error".
Este evento "salta" cuando se produce un error referente a la base de datos, tiene varios argumentos que te pueden ayudar.
Puedes controlarlo en este evento poniendo tu propio Messagebox("ERROR BD","ERROR en base de Datos, clave duplicada", Exclamation!) O algo así, y luego hacer un "Return 1" para que Power Builder no te muestre su FEO MENSAJE.
Y 2ª cosa:
Antes de hacer el UPDATE del datawindow, hacer un
SELECT Count(*) Into :ll_filas
FROM area
WHERE are_cod = :are_cod_pantalla
AND are_descripcion = are_descripcion_pantalla;
If ll_filas > 0 Then
Messagebox("ERROR BD","Clave duplicada", Exclamation!)
Return
End If
Bueno privatte, espero haber solucionado tu problema,
Yo te aconsejaría (si puedes)
Que utilices la 1ª opción de todas,
Eso es lo que me falta conceptos, aveces
uno sabe las cosas pero no sabe como aplicarlas
Dejame ver si entendí
Lo que pasa
Es que no se puede repetir ni código ni descripción
Entonces tu me aconsejas que deje solo código como porque y descripción lo compare con código
Esa tabla es de áreas
O sea
1 informática
2 crédito etc
entonce tambien tiene q haver un mantenedor
Por ejemplo
1 crédito
2 informática
Saludos. janomix 2003
No me ha quedado claro si
Quieres meter los valores en la tabla desde una aplicación hecha en Power Builder o quieres meter los datos desde una herramienta de Bases de Datos...
Yo entendí que querías hacerlo desde la aplicación y todo lo que te conté en el anterior correo era referente a ello, ¿ok? Y claro que necesitarías hacer el mantenedor de esa tabla (es muy sencillo para ti, je je).
La primary key debe estar formada por campos que el usuario no pueda manipular, y como se supone que el usuario puede meter la descripción, por eso no se incluye en la primary key este campo...
Tienes el inconveniente que el usuario puede meter el área de "informática" todas las veces que quiera, pero eso ya es cuenta suya y se debe preocupar de mo repetir las descripciones de área.
Si nos ponemos en el caso extremo, cuando le diese a Actualizar podrías recoger (vía GetItemString) el valor de la descripción, hacer una select sobre la tabla de área, ver si existe esa descripción y en caso afirmativo sacar un mensaje tal como :
MessageBox("ATENCIÓN","La descripción ya se encuentra en la Base de Datos", Exclamation!)
Return 1 // Para que no haga el Update del datawindow.
Si por el contrario, quieres introducir los valores desde una herramienta externa (porque son valores "fijos" que nunca se va a añadir nuevos ni modificar los que insertes ahora), puedes meterlos como quieras, (respetando la prímary key).
Espero haber aclarado tu tema,
ya sabes que si no es así...
Aquí estamos...
Ánimo y métele caña a esas tablas que son pan comido.
Al campo descripción le agregue un unique constarint eso no me permite duplicar datos ahí estamos ok.
Ademas este campo no acepta campos nulos el campo código lo puse en autoincrement
Pero lo raro es que cuando hago un update me alega por el campo descripción siendo que este esta not null
Que pasar master
Saludos
Ok, entiendo,
descripción, ya no forma parte de la primary pero le has puesto la restricción "NOT NULL". OK.
No entiendo entonces cual puede ser el error...
Asegurate que cuando haces Update sobre el Datawindow,
ambos cambos(código y descripción) tienen información, utiliza el GetItem.
Si ves que tienen valores antes de hacer el Update, mira a ver si es problema del autoincrement, que está actuando de forma extraña.
Te sugiero que pruebes de menos a mayor, me explico,
1º crea la tabla sencilla, con la primary y el campo descripción sin restricciones.
Si te funciona, complicaló un poco, metiendo la restricción de NOT NULL al campo "descripcion" y si te funciona esto, pruebas a merle el "increment" al campo código, poco a poco hasta llegar a lo que quieres.
Me cuentas...

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas