Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

lunes, 13 de enero de 2014

Resetear campo autoincrementable (serial) en Postgre 9.3

Tengo una base de datos llamada "Prueba" con una tabla "phonebook", la cual tiene un campo autoincrementable (tipo serial) llamado "ID":


Cuando se crea un dato serial usando el pgAdmin, Postgre automáticamente nos crea una secuencia (en este caso llamada "phonebook_ID_seq") a la cual el campo serial está vinculado mediante la siguiente instrucción:

ALTER TABLE phonebook ALTER COLUMN "ID" SET DEFAULT nextval('"phonebook_ID_seq"'::regclass);

Para Postgre, un dato serial es un dato Integer con la función "nextval".

Esta es mi situación:
Luego de añadir y borrar varios registros a la tabla "phonebook", y finalmente dejarla vacía, quiero resetear el valor del campo "ID" a 1.

Al igual que en MySql, Postgre tiene una función llamada "setval" que me permite ponerle un valor arbitrario a la secuencia desde el cual continuará con los incrementos.
En el pgAdmin seleccionamos el campo "ID", abrimos la ventana de queries mediante el botón "Execute Arbitrary Queries" (el que tiene una lupa y el texto "SQL"), e ingresamos el siguiente query:

select setval('"phonebook_ID_seq"',1);

Hay que notar que lo que se altera es la secuencia, no el campo "ID". Hay que tener cuidado de poner el nombre de la secuencia entre comillas dobles dentro de las comillas simples. Como Postgre es Case Sensitive, saltarán errores si omitimos las comillas dobles y si el nombre de la secuencia contiene mayúsculas.

En la ventana de queries quedará así:


Si todo sale bien, nos aparecerá el valor al que hemos reseteado la secuencia. No tiene que ser 1, puede ser cualquier valor que queramos.

miércoles, 8 de enero de 2014

Postgre 9.3: Errores 42501 y 42703:

Tengo la siguiente base de datos Prueba instalada en un servidor local de Postgre versión 9.3, la cual tiene una sola tabla "phonebook" cuya estructura copié de algún sitio de Internet (al instalar Postgre se tiene la opción de instalar también el pgAdmin):


El Owner de la base de datos y de la tabla es el superusuario "postgre". La base de datos Prueba tiene como esquema por defecto (Default Schema) igual a público (public), también sus privilegios son públicos.

También he creado un usuario "user01" con las siguientes propiedades:


Al conectar una aplicación en C# mediante el usuario "user01", usando Npgsql (el cual se puede instalar junto con el Postgre usando la aplicación Stack Builder que también viene con el instalador del Postgre) y luego de ver los datos de la tabla phonebook todo iba bien; pero cuando quería modificar la tabla phonebook con un update, insert ó delete me arrojaba el siguiente error:


"Error 42501: permiso denegado a la secuencia phonebook_ID_seq"

Este error salta si el usuario con el que intento modificar la tabla no es su dueño (owner). No interesa si la base de datos tiene como dueño al superusuario "postgre", la tabla debe tener como dueño al usuario que intenta modificarla.

Para cambiar al dueño de la tabla phonebook de "postgre" a "user01" basta este script:

ALTER TABLE phonebook
  OWNER TO user01;

Y entonces al usar la siguiente sentencia insert desde C#:

string query = @"insert into phonebook (phone, firstname, lastname, address) values ('1234', 'Wert', 'Asdlo', 'Fake Street 123')";

Los datos se guardaban correctamente, pero al querer actualizar o borrar: 

string query1 = @"Update phonebook set phone ='0000', firstname ='Carry', lastname ='Doe', address = 'No signed' where ID = 1";
string query2 = "delete from phonebook where ID = 1";

Me saltaba el siguiente error:


"Error 42703: no existe la columna id"

Lo extraño es que la tabla phonebook sí tiene una columna llamada "ID". Buscando por internet, hallé aquí la solución: se debe poner el nombre del campo que contiene mayúsculas entre comillas:

string query1 = "Update phonebook set phone ='0000', firstname ='Carry', "
" lastname ='Doe', address = 'No signed' where \"ID\" = 1";
string query2 = "delete from phonebook where \"ID\" = 1";

El caracter \ le indica al C# que la comilla que le sigue no indica el final de la cadena. El motor del Postgre convierte todos los nombres de las columnas en una sentencia sql a minúsculas. Por ahí leí que, internamente, Postgre es Case Sensitive.