Unique Constraint error creating tables in PostgreSQL (migrated from MySQL) - postgresql

I read with great enthusiasm the question entitled Migrate from MySQL to PostgreSQL on Linux (Kubuntu). The Star Wars theme made it that much more entertaining. But I've run into an issue regarding Unique Constraints in PostgreSQL.
I followed the above post closely to create a PostgreSQL DDL using sqlt. The thought process was to create the schema/tables first and then import the data. However 57 of my 72 tables use CONSTRAINT "userid" UNIQUE ("user_id", "key")
Here is an example of one of the tables:
CREATE TABLE "account_otherserviceinfo" (
"id" serial NOT NULL,
"user_id" bigint NOT NULL,
"key" character varying(50) NOT NULL,
"value" text NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "user_id" UNIQUE ("user_id", "key")
);
When I copy these tables into my PostgreSQL DB using the Query tool in pgadmin3, I get the following error:
ERROR: relation "user_id" already exists
SQL state: 42P07
I did not design this database schema. I am only helping with the migration process. When reading the documentation on Unique Constraints, it appears that it is Ok to use the same name as long as it's in a different table. http://www.postgresql.org/docs/8.3/static/ddl-constraints.html. Am I misinterpreting this?
Any suggestions or pointers would be greatly appreciated.
Thank you!
PS: Thanks https://stackoverflow.com/users/59087/dave-jarvis and https://stackoverflow.com/users/26534/michael-trausch for getting me this far ;-)

When reading the documentation on
Unique Constraints, it appears that it
is Ok to use the same name as long as
it's in a different table.
I'm not sure what part of the documentation you're reading, but you're misinterpreting it. Constraint names have to be globally unique. So you can have as many of these UNIQUE ("user_id", "key") as you like, but you can't name every one of them "user_id".

You can get around this type of issue by giving your constraints more detailed names.
You will need to come up with a naming standard for you database objects to avoid this type of issue. Maybe something like type_schema_tablename_columnname. So for example uidx_public_account_otherserviceinfor_user_id_key. That type of name will make sure you don't have issues and makes it easy to figure out what object an error message is referring to. You can debate the clearest way to implement what I said, but the key point is come up with a standard to use for all objects that works for your enviroment.

You should not use user_id as constraint name because it is already used as column name.

Related

PostgreSQL: arrays of foreign keys?

I have a PostgreSQL table containing a bunch of foreign keys pointing to another table:
create table foo (
hourly00 uuid references hourly(id),
hourly01 uuid references hourly(id),
-- etc.
hourly23 uuid references hourly(id),
-- omit rest
);
Admittedly, this looks silly (and I am lucky to have only 24 of such keys), but I have not found anything better.
In the meantime, I stumbled on PostgreSQL documentation about arrays (I did not know about PostgreSQL arrays before). I got an idea and I tried this:
create table foo (
hourly uuid[24] references hourly(id)
);
which, of course, immediately resulted in an error:
ERROR: foreign key constraint "main_hourly_fkey" cannot be implemented
DETAIL: Key columns "hourly" and "id" are of incompatible types: uuid[] and uuid.
But then I got another idea — to ask about my situation on StackOverflow. So my question is: does PostgreSQL provide means for doing something like this, i.e. for having an array of foreign keys in a table? Is it perhaps doable with some PL/*? Or perhaps with some other database system? I am willing to do my own research, but I have no idea as to where to look.

Error 42P01. not issue with braces

Hello I am fairly new to PostgreSQL, I keep getting the following error code:
ERROR: relation "contact" does not exist
********** Error **********
ERROR: relation "contact" does not exist
SQL state: 42P01
Questions regarding this error code have been mentioned a lot on Stack Overflow and online, however I have tried checking for any braces that may change the letter case sensitivity of my code and was unable to find any.
This is how I've attempted to create the table:
CREATE TABLE CONTACT (
CONTACT_ID INTEGER,
BUILDING_NO INTEGER,
POSTCODE VARCHAR,
PHONE_NO INTEGER,
EMAIL VARCHAR,
CONSTRAINT PK_CONTACT_ID PRIMARY KEY (CONTACT_ID));
I would appreciate anyones help, and am sorry if this question may have been repeated, thank you guys :)
The issue is that you are creating your objects (tables) in the wrong order.
Create contact before you create tables that use contact as a foreign key-- or, create the foreign keys after you've created all your tables. The first table "student" is referencing contact, which has not been created yet.
EDIT:
Also, your phone number fields should not be integers, they should be text or varchar. If you're dead set on a numeric type, use bigint instead if integer.
I copied and pasted you code and it worked for me. Could it be something with your postgresql setup?
EDITS BELOW
Alright so I'm going to add more to the solution
Like Joe Love Said, You have issues with the ordering. The proper ordering of your tables should be something like Contact, Status, Student, Company, Application and then the rest of the queries.
In your Application Table, the line
CONSTRAINT FK_STATUS_ID FOREIGN KEY (STATUS_ID) REFERENCES STATUS (STATUS_ID),
Will give you an error.
Its because in the STATUS Table, you have set the ID as a VARCHAR and in the Application table, the Status is an INTEGER.
You still have some issues with the Application query referencing the Company Table as well. If you fix them, you should be good.

Creating a "table of tables" in PostgreSQL or achieving similar functionality?

I'm just getting started with PostgreSQL, and I'm new to database design.
I'm writing software in which I have various plugins that update a database. Each plugin periodically updates its own designated table in the database. So a plugin named 'KeyboardPlugin' will update the 'KeyboardTable', and 'MousePlugin' will update the 'MouseTable'. I'd like for my database to store these 'plugin-table' relationships while enforcing referential integrity. So ideally, I'd like a configuration table with the following columns:
Plugin-Name (type 'text')
Table-Name (type ?)
My software will read from this configuration table to help the plugins determine which table to update. Originally, my idea was to have the second column (Table-Name) be of type 'text'. But then, if someone mistypes the table name, or an existing relationship becomes invalid because of someone deleting a table, we have problems. I'd like for the 'Table-Name' column to act as a reference to another table, while enforcing referential integrity.
What is the best way to do this in PostgreSQL? Feel free to suggest an entirely new way to setup my database, different from what I'm currently exploring. Also, if it helps you answer my question, I'm using the pgAdmin tool to setup my database.
I appreciate your help.
I would go with your original plan to store the name as text. Possibly enhanced by additionally storing the schema name:
addin text
,sch text
,tbl text
Tables have an OID in the system catalog (pg_catalog.pg_class). You can get those with a nifty special cast:
SELECT 'myschema.mytable'::regclass
But the OID can change over a dump / restore. So just store the names as text and verify the table is there by casting it like demonstrated at application time.
Of course, if you use each tables for multiple addins it might pay to make a separate table
CREATE TABLE tbl (
,tbl_id serial PRIMARY KEY
,sch text
,name text
);
and reference it in ...
CREATE TABLE addin (
,addin_id serial PRIMARY KEY
,addin text
,tbl_id integer REFERENCES tbl(tbl_id) ON UPDATE CASCADE ON DELETE CASCADE
);
Or even make it an n:m relationship if addins have multiple tables. But be aware, as #OMG_Ponies commented, that a setup like this will require you to execute a lot of dynamic SQL because you don't know the identifiers beforehand.
I guess all plugins have a set of basic attributes and then each plugin will have a set of plugin-specific attributes. If this is the case you can use a single table together with the hstore datatype (a standard extension that just needs to be installed).
Something like this:
CREATE TABLE plugins
(
plugin_name text not null primary key,
common_int_attribute integer not null,
common_text_attribute text not null,
plugin_atttributes hstore
)
Then you can do something like this:
INSERT INTO plugins
(plugin_name, common_int_attribute, common_text_attribute, hstore)
VALUES
('plugin_1', 42, 'foobar', 'some_key => "the fish", other_key => 24'),
('plugin_2', 100, 'foobar', 'weird_key => 12345, more_info => "10.2.4"');
This creates two plugins named plugin_1 and plugin_2
Plugin_1 has the additional attributes "some_key" and "other_key", while plugin_2 stores the keys "weird_key" and "more_info".
You can index those hstore columns and query them very efficiently.
The following will select all plugins that have a key "weird_key" defined.
SELECT *
FROM plugins
WHERE plugin_attributes ? 'weird_key'
The following statement will select all plugins that have a key some_key with the value the fish:
SELECT *
FROM plugins
WHERE plugin_attributes #> ('some_key => "the fish"')
Much more convenient than using an EAV model in my opinion (and most probably a lot faster as well).
The only drawback is that you lose type-safety with this approach (but usually you'd lose that with the EAV concept as well).
You don't need an application catalog. Just add the application name to the keys of the table. This of course assumes that all the tables have the same structure. If not: use the application name for a table name, or as others have suggested: as a schema name( which also would allow for multiple tables per application).
EDIT:
But the real issue is of course that you should first model your data, and than build the applications to manipulate it. The data should not serve the code; the code should serve the data.

In postgresql: Clarification on "CONSTRAINT foo_key PRIMARY KEY (foo)"

Sorry if this is a dead simple question but I'm confused from the documentation and I'm not getting any clear answers from searching the web.
If I have the following table schema:
CREATE TABLE footable
(
foo character varying(10) NOT NULL,
bar timestamp without time zone,
CONSTRAINT pk_foo PRIMARY KEY (foo)
);
and then use the query:
SELECT bar FROM footable WHERE foo = '1234567890';
Will the select query find the given row by searching an index or not? In other word: does the table have a primary key (which is foo) or not?
Just to get it clear. I'm used to specifying "PRIMARY KEY" after the column I'm specifying like this:
"...foo character varying(10) PRIMARY KEY, ..."
Does it change anything?
Why not look at the query plan and find out yourself? The query plan will tell you exactly what indexes are being used, so you don't have to guess. Here's how to do it:
http://www.postgresql.org/docs/current/static/sql-explain.html
But in general, it should use the index in this case since you specified the primary key in the where clause and you didn't use something that could prevent it from using it (a LIKE, for example).
It's always best to look at the query plan to verify it for sure, then there's no doubt.
In both cases, the primary key can be used but it depends. The optimizer will make a choice depending on the amount of data, the statistics, etc.
Naming the constraint can make debugging and error handling easier, you know what constraint is violated. Without a name, it can be confusing.

django: manually adding a foreign key column (newcolumn_id_refs_id_4bfb2ece ?)

I need to add a foreign key field to an existing django model/postgres table. As per the django documentation, I ran the 'sqlall myapp' command to 'work out the difference'.
The obvious difference is that the table in question now has an extra column with a new contraint, which looks like this:
ALTER TABLE "myapp_mytable" ADD CONSTRAINT newcolumn_id_refs_id_4bfb2ece
FOREIGN KEY ("newcolumn_id") REFERENCES "myapp_theothertable" ("id")
DEFERRABLE INITIALLY DEFERRED;
Before messing with my database, I'd like to understand that statement, in particular, what does the last part of newcolumn_id_refs_id_4bfb2ece refer to?
Thanks,
Martin
It will make PostgreSQL understand and enforce your foreign key to the other table and guarantee there won't be anything in myapp_table.newcolumn that can't be found in myapp_theothertable.id
Actually, your django app will work just fine even without that constraint. However, it's a good idea to have one in place, and if you do afterwards a dumpdata - loaddata -cycle, it will be created.