How to use JSON array in JOIN? - postgresql

I have got follow data base schema:
CREATE TABLE "public"."regions" (
"id" Integer DEFAULT nextval('regions_id_seq'::regclass) NOT NULL,
"ru_name" Character Varying( 100 ),
"translite_name" Character Varying( 100 ),
PRIMARY KEY ( "id" ) );
;
CREATE TABLE "public"."tokens" (
"user_id" BigInt NOT NULL,
"token_start_date" Timestamp Without Time Zone NOT NULL,
"token_end_date" Timestamp Without Time Zone NOT NULL,
"regions" JSON,
"id" Character( 1 ) NOT NULL,
"access_token" Character Varying( 50 ) NOT NULL,
PRIMARY KEY ( "id" ) );
;
CREATE TABLE "public"."users" (
"id" BigInt DEFAULT nextval('user_id_sequence'::regclass) NOT NULL,
"registration_date" Timestamp Without Time Zone NOT NULL,
"name" Character Varying( 50 ) NOT NULL,
"lastname" Character Varying NOT NULL,
"email" Character Varying NOT NULL,
PRIMARY KEY ( "id" ),
CONSTRAINT "unique_users_email" UNIQUE( "email" ) );
;
I need to display for every user date of expiring token and regions names for this token.
Something like:
user_id token_end_date region_as_json_object
5 "2021-12-27" [{id: 1, ru_name:"Region1"}, {id: 2, ru_name:"Region2"}]
I wrote next code:
SELECT
ru_name
FROM "tokens"
JOIN regions ON regions.id = ANY (json_array_elements_text(regions) )
WHERE user_id = 5 ;
But it does not work.
sample data:
--
-- PostgreSQL database dump
--
-- Dumped from database version 13.1
-- Dumped by pg_dump version 13.1
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
SET default_tablespace = '';
SET default_table_access_method = heap;
--
-- Name: regions; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.regions (
id integer NOT NULL,
ru_name character varying(100),
fz223_name character varying(100),
fz44_name character varying(100),
translite_name character varying(100)
);
ALTER TABLE public.regions OWNER TO postgres;
--
-- Name: regions_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE public.regions_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.regions_id_seq OWNER TO postgres;
--
-- Name: regions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--
ALTER SEQUENCE public.regions_id_seq OWNED BY public.regions.id;
--
-- Name: tokens; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.tokens (
id character(1) NOT NULL,
user_id bigint NOT NULL,
token_start_date timestamp without time zone NOT NULL,
token_end_date timestamp without time zone NOT NULL,
access_token character varying(50) NOT NULL,
regions json
);
ALTER TABLE public.tokens OWNER TO postgres;
--
-- Name: users; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.users (
id bigint DEFAULT nextval('public.user_id_sequence'::regclass) NOT NULL,
name character varying(50) NOT NULL,
lastname character varying NOT NULL,
email character varying NOT NULL,
registration_date timestamp without time zone NOT NULL
);
ALTER TABLE public.users OWNER TO postgres;
--
-- Name: regions id; Type: DEFAULT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.regions ALTER COLUMN id SET DEFAULT nextval('public.regions_id_seq'::regclass);
--
-- Data for Name: regions; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO public.regions VALUES
(1, 'Адыгейская республика', 'Adygeya_Resp', 'Adygeja_Resp', 'Adygejskaya_respublika'),
(2, 'Алтайский край', 'Altayskii__krai', 'Altajskij_kraj', 'Altajskij_kraj'),
(3, 'Алтайская республика', 'Altay_Resp', 'Altaj_Resp', 'Altajskaya_respublika'),
(4, 'Амурская область', 'Amurskaya_obl', 'Amurskaja_obl', 'Amurskaya_oblast'),
(5, 'Архангельская область', 'Arhangelskaya_obl', 'Arkhangelskaja_obl', 'Arhangelskaya_oblast'),
(6, 'Астраханская область', 'Astrahanskaya_obl', 'Astrakhanskaja_obl', 'Astrahanskaya_oblast'),
(7, 'Байконур', 'Baikonur_g', 'Bajkonur_g', 'Bajkonur'),
(8, 'Башкортостан', 'Bashkortostan_Resp', 'Bashkortostan_Resp', 'Bashkortostan'),
(9, 'Белгородская область', 'Belgorodskaya_obl', 'Belgorodskaja_obl', 'Belgorodskaya_oblast'),
(10, 'Брянская область', 'Brianskaya_obl', 'Brjanskaja_obl', 'Bryanskaya_oblast'),
(11, 'Бурятская область', 'Buryatiya_Resp', 'Burjatija_Resp', 'Buryatskaya_oblast');
--
-- Data for Name: tokens; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO public.tokens VALUES
('1', 3, '2020-03-05 00:00:00', '2020-03-08 00:00:00', 'sdfa78saaf4', NULL),
('2', 3, '2020-04-08 00:00:00', '2020-04-18 00:00:00', 'asasdfgkfaf4', NULL),
('3', 3, '2020-05-15 00:00:00', '2020-09-25 00:00:00', '934rfeasfsad', '[1,2,4]'),
('4', 3, '2020-05-15 00:00:00', '2020-09-25 00:00:00', '934rfeasfsad', '[4,5,7]'),
('5', 5, '2021-05-15 00:00:00', '2021-12-25 00:00:00', '934rfeasfsad', '[1,4,6,8]'),
('6', 5, '2021-06-15 00:00:00', '2022-01-25 00:00:00', '934rfeasfsad', '[12]');
--
-- Data for Name: users; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO public.users VALUES
(3, 'Mike', 'Klinton', 'mike#gmail.com', '2010-01-02 00:00:00'),
(5, 'Piter', 'Miklson', 'piter#gmail.com', '2011-01-02 00:00:00');
--
-- Name: regions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
--
SELECT pg_catalog.setval('public.regions_id_seq', 1, false);
--
-- Name: regions regions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.regions
ADD CONSTRAINT regions_pkey PRIMARY KEY (id);
--
-- Name: tokens tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.tokens
ADD CONSTRAINT tokens_pkey PRIMARY KEY (id);
--
-- Name: users unique_users_email; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.users
ADD CONSTRAINT unique_users_email UNIQUE (email);
--
-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
--
-- Name: tokens userr_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.tokens
ADD CONSTRAINT userr_id_fk FOREIGN KEY (user_id) REFERENCES public.users(id) MATCH FULL ON UPDATE CASCADE ON DELETE CASCADE;
--
-- PostgreSQL database dump complete
--

select user_id, token_end_date::date,
json_agg(json_build_object('id',region_id,'ru_name',ru_name)) as regions_json_object
from
(
select user_id, token_end_date,
json_array_elements_text(regions)::integer as region_id
from tokens
) as t
join regions on t.region_id = regions.id
group by user_id, token_end_date;

Try this :
SELECT
ru_name
FROM
( SELECT json_array_elements_text(regions) AS r
FROM public.tokens
WHERE user_id = 5
) AS r
JOIN public.regions
ON regions.id = r :: integer ;
see the result in dbfiddle

You can use CROSS JOIN and after collecting, data use JOIN for combine data.
Demo
with data as (
select
t.*,
(ej.value ->> 'id')::int as region_id
from
"public"."tokens" t
cross join json_array_elements(t.regions) ej
where
user_id = 5
)
select
r.ru_name
from
"public"."regions" r
inner join data d on d.region_id = r.id

Related

Pg_dump -s (schema) of tables omits the defaults for columns that use nextval()

After defining the table, the script generated by PGAdmin via rightclick->SCRIPT->CREATE SCRIPT, looks like this:
-- DROP TABLE public.arr;
CREATE TABLE public.arr
(
rcdno integer NOT NULL DEFAULT nextval('arr_rcdno_seq'::regclass),
rcdstate character varying(10) COLLATE pg_catalog."default" DEFAULT 'ACTIVE'::character varying,
rcdserial integer NOT NULL DEFAULT 0,
msrno integer NOT NULL DEFAULT nextval('arr_msrno_seq'::regclass),
mobileid character varying(50) COLLATE pg_catalog."default" NOT NULL,
edittimestamp timestamp without time zone DEFAULT now(),
editor character varying(20) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT pk_arr PRIMARY KEY (mobileid, msrno, rcdserial)
)
After using >pg_dump -s -U webmaster -W -F p Test > c:\temp\Test.sql, the table definition in the script OMITS the defaults for the 2 original "serial" columns. This means that the pg_dump script doesn't create the table correctly when it is run!
--
-- Name: arr; Type: TABLE; Schema: public; Owner: webmaster
--
CREATE TABLE public.arr (
rcdno integer NOT NULL, -- default missing!
rcdstate character varying(10) DEFAULT 'ACTIVE'::character varying,
rcdserial integer DEFAULT 0 NOT NULL,
msrno integer NOT NULL, -- default missing!
mobileid character varying(50) NOT NULL,
edittimestamp timestamp without time zone DEFAULT now(),
editor character varying(20) NOT NULL
);
ALTER TABLE public.arr OWNER TO webmaster;
--
-- Name: arr_msrno_seq; Type: SEQUENCE; Schema: public; Owner: webmaster
--
CREATE SEQUENCE public.arr_msrno_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.arr_msrno_seq OWNER TO webmaster;
--
-- Name: arr_msrno_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: webmaster
--
ALTER SEQUENCE public.arr_msrno_seq OWNED BY public.arr.msrno;
--
-- Name: arr_rcdno_seq; Type: SEQUENCE; Schema: public; Owner: webmaster
--
CREATE SEQUENCE public.arr_rcdno_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.arr_rcdno_seq OWNER TO webmaster;
--
-- Name: arr_rcdno_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: webmaster
--
ALTER SEQUENCE public.arr_rcdno_seq OWNED BY public.arr.rcdno;
EDIT: After the generated script has been run, the statement
into public.arr(mobileid, editor)
values
('12345', 'nolaspeaker')
generates
ERROR: null value in column "rcdno" violates not-null constraint DETAIL: Failing row contains (null, ACTIVE, 0, null, 12345, 2020-08-18 08:54:41.34052, nolaspeaker). SQL state: 23502
Which indicates that I am correct to assert that the script omits the default values for the rcdno column!
The ALTER TABLE statements that set the default values are towards the end of the dump, close to where the ALTER SEQUENCE ... OWNED BY are.
If they don't get restored, that might be because there was a problem creating the sequences.
Look at the error messages from the restore, particularly the first ones (later ones are often consequences of the earlier ones).
The statements that assign the default values to the applicable columns come much later in the script
--
-- Name: arr rcdno; Type: DEFAULT; Schema: public; Owner: webmaster
--
ALTER TABLE ONLY public.arr ALTER COLUMN rcdno SET DEFAULT nextval('public.arr_rcdno_seq'::regclass);
--
-- Name: arr msrno; Type: DEFAULT; Schema: public; Owner: webmaster
--
ALTER TABLE ONLY public.arr ALTER COLUMN msrno SET DEFAULT nextval('public.arr_msrno_seq'::regclass);
So you have to be careful if you cut-and-paste a table definition out of the script!

How to migrate database schema from Identity 2.2.0 to 3.0.0-rc1-final

I've been playing around migrating an existing application running on MVC5 with ASP.NET Identity 2.2.0 having trouble finding proper information, i'd like to ask how you are supposed to do this migration?
I've used a couple of hours on this problem and have found a solution that allows me to log in with Identity 3.0.0-rc1-final with ef7 on my old but migrated database.
I will post what I did as an answer, but i'd very much like inspiration or other ways to have done it.
First I generated a new migration with the following command
dnx ef migration add MigrateIdentityFrameworkFrom2to3
This generated two files in the folder Migrations
XYZ_MigrateIdentityFrameworkFrom2to3.cs
ApplicationDbContextModelSnapshot.cs
The snapshot is the same as with ef6, a description of how your database looks. the other file is the actual migration containing the Up and Down commands for migrating your database.
The problems with migrating to the Identity 3.0.0-rc1-final schema appeared to be
AspNetRoles Two new database columns (ConcurrencyStamp, NormalizedName)
AspNetUsers 4 new columns (ConcurrencyStamp,LockoutEnd,NormalizedEmail,NormalizedUserName)
New Table (AspNetRoleClaims)
And in general the primary key on AspNetUsers and AspNetRole and Foreign Keys to theese tables had changed in length, from 128 to 450
The following is the Up and Down commands I used to be able to log in to my MVC6 application:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId", "AspNetUserRoles");
migrationBuilder.DropPrimaryKey("PK_dbo.AspNetRoles", "AspNetRoles");
migrationBuilder.Sql(#"
ALTER TABLE[AspNetRoles]
ALTER COLUMN[Id] NVARCHAR(450) NOT NULL
ALTER TABLE[AspNetUserRoles]
ALTER COLUMN[RoleId] NVARCHAR(450) NOT NULL");
migrationBuilder.AddPrimaryKey("PK_dbo.AspNetRoles", "AspNetRoles", "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId", "AspNetUserRoles", "RoleId", "AspNetRoles", principalColumn:"Id");
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId", "AspNetUserClaims");
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId", "AspNetUserLogins");
migrationBuilder.DropForeignKey("FK_dbo.User_dbo.AspNetUsers_IdentityUser_Id", "User");
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId", "AspNetUserRoles");
migrationBuilder.DropPrimaryKey("PK_dbo.AspNetUsers", "AspNetUsers");
migrationBuilder.Sql(#"
ALTER TABLE [AspNetUsers]
ALTER COLUMN [Id] NVARCHAR(450) NOT NULL
ALTER TABLE[AspNetUserRoles]
ALTER COLUMN[UserId] NVARCHAR(450) NOT NULL
ALTER TABLE[User]
ALTER COLUMN[IdentityUser_Id] NVARCHAR(450) NOT NULL
ALTER TABLE[AspNetUserLogins]
ALTER COLUMN[UserId] NVARCHAR(450) NOT NULL
ALTER TABLE[AspNetUserClaims]
ALTER COLUMN[UserId] NVARCHAR(450) NOT NULL");
migrationBuilder.AddPrimaryKey("PK_dbo.AspNetUsers", "AspNetUsers", "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId", "AspNetUserRoles", "UserId", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddForeignKey("FK_dbo.User_dbo.AspNetUsers_IdentityUser_Id", "User", "IdentityUser_Id", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId", "AspNetUserLogins", "UserId", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId", "AspNetUserClaims", "UserId", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddColumn<string>(name: "ConcurrencyStamp", table: "AspNetRoles", nullable: true);
migrationBuilder.AddColumn<string>(name: "NormalizedName", table: "AspNetRoles", nullable: true);
migrationBuilder.Sql(#"UPDATE AspNetRoles SET NormalizedName = UPPER(Name)");
migrationBuilder.AddColumn<string>(name: "ConcurrencyStamp", table: "AspNetUsers", nullable: true);
migrationBuilder.AddColumn<string>(name: "LockoutEnd", table: "AspNetUsers", nullable: true);
migrationBuilder.AddColumn<string>(name: "NormalizedEmail", table: "AspNetUsers", nullable: true);
migrationBuilder.AddColumn<string>(name: "NormalizedUserName", table: "AspNetUsers", nullable: true);
migrationBuilder.Sql(#"UPDATE AspNetUsers SET NormalizedEmail = UPPER(Email), NormalizedUserName = UPPER(UserName)"); // MVC6 utilizes Email as login by default with forms authentication, and searches for the email in NormalizedUserName, I changed the login formular to utilize UserName instead of email when logging in, alternatively you can put in the email as NormalizedUserName.
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_IdentityRoleClaim<string>", x => x.Id);
table.ForeignKey(
name: "FK_IdentityRoleClaim<string>_IdentityRole_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.AddColumn<string>(name: "ProviderDisplayName", table: "AspNetUserLogins", nullable: true);
migrationBuilder.DropIndex(
name: "RoleNameIndex",
table: "AspNetRoles");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.DropIndex(
name: "UserNameIndex",
table: "AspNetUsers");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId", "AspNetUserRoles");
migrationBuilder.DropPrimaryKey("PK_dbo.AspNetRoles", "AspNetRoles");
migrationBuilder.Sql(#"ALTER TABLE [AspNetRoles]
ALTER COLUMN [Id] NVARCHAR(128) NOT NULL
ALTER TABLE[AspNetUserRoles]
ALTER COLUMN[RoleId] NVARCHAR(128) NOT NULL");
migrationBuilder.AddPrimaryKey("PK_dbo.AspNetRoles", "AspNetRoles", "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId", "AspNetUserRoles", "RoleId", "AspNetRoles", principalColumn: "Id");
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId", "AspNetUserClaims");
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId", "AspNetUserLogins");
migrationBuilder.DropForeignKey("FK_dbo.User_dbo.AspNetUsers_IdentityUser_Id", "User");
migrationBuilder.DropForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId", "AspNetUserRoles");
migrationBuilder.DropPrimaryKey("PK_dbo.AspNetUsers", "AspNetUsers");
migrationBuilder.Sql(#"ALTER TABLE [AspNetUsers]
ALTER COLUMN [Id] NVARCHAR(128) NOT NULL
ALTER TABLE[AspNetUserRoles]
ALTER COLUMN[UserId] NVARCHAR(128) NOT NULL
ALTER TABLE[User]
ALTER COLUMN[IdentityUser_Id] NVARCHAR(128) NOT NULL
ALTER TABLE[AspNetUserLogins]
ALTER COLUMN[UserId] NVARCHAR(128) NOT NULL
ALTER TABLE[AspNetUserClaims]
ALTER COLUMN[UserId] NVARCHAR(128) NOT NULL");
migrationBuilder.AddPrimaryKey("PK_dbo.AspNetUsers", "AspNetUsers", "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId", "AspNetUserRoles", "UserId", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddForeignKey("FK_dbo.User_dbo.AspNetUsers_IdentityUser_Id", "User", "IdentityUser_Id", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId", "AspNetUserLogins", "UserId", "AspNetUsers", principalColumn: "Id");
migrationBuilder.AddForeignKey("FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId", "AspNetUserClaims", "UserId", "AspNetUsers", principalColumn: "Id");
migrationBuilder.DropTable("AspNetRoleClaims");
migrationBuilder.DropColumn(name: "ConcurrencyStamp", table: "AspNetRoles");
migrationBuilder.DropColumn(name: "NormalizedName", table: "AspNetRoles");
migrationBuilder.DropColumn(name: "ConcurrencyStamp", table: "AspNetUsers");
migrationBuilder.DropColumn(name: "LockoutEnd", table: "AspNetUsers");
migrationBuilder.DropColumn(name: "NormalizedEmail", table: "AspNetUsers");
migrationBuilder.DropColumn(name: "NormalizedUserName", table: "AspNetUsers");
migrationBuilder.DropColumn(name: "ProviderDisplayName", table: "AspNetUserLogins");
migrationBuilder.DropIndex(
name: "RoleNameIndex",
table: "AspNetRoles");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "Name");
migrationBuilder.DropIndex(
name: "EmailIndex",
table: "AspNetUsers");
migrationBuilder.DropIndex(
name: "UserNameIndex",
table: "AspNetUsers");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "UserName");
}
Here is an SQL script to convert Identity 2 database to Identity Core (or Identity 3 if you prefer). Notes:
This script was generated by the Visual Studio Schema Compare tool and then modified by hand. The goal of the script is to migrate the schema without dropping the AspNetUsers table. The other tables are dropped and recreated in the process and data is copied. If you have modifications to tables other than the users table or if you have modified the PK of the users table you should modify the script accordingly. There are several changes compared to the default schema related to PK sizes.
The users table has a PK of NVARCHAR(128) as it has in Identity 2 rather than NVARCHAR(450) what Identity 3 uses. All relationship in other tables are also changed to NVARCHAR(128)
The roles table has a PK of NVARCHAR(128). There were several warnings related to maximum key size exceeding 900 bytes for keys including the role id.
There are still some warning related to Login provider having longer keys but I think it is reasonable risk to let the ProviderKey be 450 characters as the actual external provider may use large keys. Note that the default ASP.NET Identity 3 schema has even larger primary keys.
I originally published the script here - https://github.com/Eirenarch/Identity2to3 I might modify this version if I need further changes or discover bugs.
PRINT N'Dropping [dbo].[AspNetUserClaims].[IX_UserId]...';
GO
DROP INDEX [IX_UserId] ON [dbo].[AspNetUserClaims];
GO
PRINT N'Dropping [dbo].[AspNetUserLogins].[IX_UserId]...';
GO
DROP INDEX [IX_UserId] ON [dbo].[AspNetUserLogins];
GO
PRINT N'Dropping [dbo].[AspNetUserRoles].[IX_RoleId]...';
GO
DROP INDEX [IX_RoleId] ON [dbo].[AspNetUserRoles];
GO
PRINT N'Dropping [dbo].[AspNetUserRoles].[IX_UserId]...';
GO
DROP INDEX [IX_UserId] ON [dbo].[AspNetUserRoles];
GO
PRINT N'Dropping [dbo].[FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId]...';
GO
ALTER TABLE [dbo].[AspNetUserRoles] DROP CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId];
GO
PRINT N'Dropping [dbo].[FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId]...';
GO
ALTER TABLE [dbo].[AspNetUserClaims] DROP CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId];
GO
PRINT N'Dropping [dbo].[FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId]...';
GO
ALTER TABLE [dbo].[AspNetUserLogins] DROP CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId];
GO
PRINT N'Dropping [dbo].[FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId]...';
GO
ALTER TABLE [dbo].[AspNetUserRoles] DROP CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId];
GO
PRINT N'Starting rebuilding table [dbo].[AspNetRoles]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetRoles] (
[Id] NVARCHAR (128) NOT NULL,
[ConcurrencyStamp] NVARCHAR (MAX) NULL,
[Name] NVARCHAR (256) NULL,
[NormalizedName] NVARCHAR (256) NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetRoles1] PRIMARY KEY CLUSTERED ([Id] ASC)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetRoles])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetRoles] ([Id], [Name], [NormalizedName])
SELECT [Id],
[Name],
UPPER([Name])
FROM [dbo].[AspNetRoles]
ORDER BY [Id] ASC;
END
DROP TABLE [dbo].[AspNetRoles];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetRoles]', N'AspNetRoles';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetRoles1]', N'PK_AspNetRoles', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
PRINT N'Creating [dbo].[AspNetRoles].[RoleNameIndex]...';
GO
CREATE NONCLUSTERED INDEX [RoleNameIndex]
ON [dbo].[AspNetRoles]([NormalizedName] ASC);
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserClaims]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserClaims] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ClaimType] NVARCHAR (MAX) NULL,
[ClaimValue] NVARCHAR (MAX) NULL,
[UserId] NVARCHAR (128) NOT NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserClaims1] PRIMARY KEY CLUSTERED ([Id] ASC)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUserClaims])
BEGIN
SET IDENTITY_INSERT [dbo].[tmp_ms_xx_AspNetUserClaims] ON;
INSERT INTO [dbo].[tmp_ms_xx_AspNetUserClaims] ([Id], [UserId], [ClaimType], [ClaimValue])
SELECT [Id],
[UserId],
[ClaimType],
[ClaimValue]
FROM [dbo].[AspNetUserClaims]
ORDER BY [Id] ASC;
SET IDENTITY_INSERT [dbo].[tmp_ms_xx_AspNetUserClaims] OFF;
END
DROP TABLE [dbo].[AspNetUserClaims];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserClaims]', N'AspNetUserClaims';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserClaims1]', N'PK_AspNetUserClaims', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
PRINT N'Creating [dbo].[AspNetUserClaims].[IX_AspNetUserClaims_UserId]...';
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserClaims_UserId]
ON [dbo].[AspNetUserClaims]([UserId] ASC);
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserLogins]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserLogins] (
[LoginProvider] NVARCHAR (128) NOT NULL,
[ProviderKey] NVARCHAR (450) NOT NULL,
[ProviderDisplayName] NVARCHAR (MAX) NULL,
[UserId] NVARCHAR (128) NOT NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserLogins1] PRIMARY KEY CLUSTERED ([LoginProvider] ASC, [ProviderKey] ASC)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUserLogins])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetUserLogins] ([LoginProvider], [ProviderKey], [ProviderDisplayName], [UserId])
SELECT [LoginProvider],
[ProviderKey],
[LoginProvider] AS [ProviderDisplayName],
[UserId]
FROM [dbo].[AspNetUserLogins]
ORDER BY [LoginProvider] ASC, [ProviderKey] ASC;
END
DROP TABLE [dbo].[AspNetUserLogins];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserLogins]', N'AspNetUserLogins';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserLogins1]', N'PK_AspNetUserLogins', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
PRINT N'Creating [dbo].[AspNetUserLogins].[IX_AspNetUserLogins_UserId]...';
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserLogins_UserId]
ON [dbo].[AspNetUserLogins]([UserId] ASC);
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserRoles]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserRoles] (
[UserId] NVARCHAR (128) NOT NULL,
[RoleId] NVARCHAR (128) NOT NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserRoles1] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUserRoles])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetUserRoles] ([UserId], [RoleId])
SELECT [UserId],
[RoleId]
FROM [dbo].[AspNetUserRoles]
ORDER BY [UserId] ASC, [RoleId] ASC;
END
DROP TABLE [dbo].[AspNetUserRoles];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserRoles]', N'AspNetUserRoles';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserRoles1]', N'PK_AspNetUserRoles', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
PRINT N'Creating [dbo].[AspNetUserRoles].[IX_AspNetUserRoles_RoleId]...';
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_RoleId]
ON [dbo].[AspNetUserRoles]([RoleId] ASC);
GO
PRINT N'Creating [dbo].[AspNetUserRoles].[IX_AspNetUserRoles_UserId]...';
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_UserId]
ON [dbo].[AspNetUserRoles]([UserId] ASC);
GO
-- CHANGE THE REST OF THE SCRIPT! We should NOT drop AspNetUsers
PRINT N'Starting rebuilding table [dbo].[AspNetUsers]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
ALTER TABLE [dbo].[AspNetUsers]
ADD [ConcurrencyStamp] NVARCHAR(MAX) NULL
GO
ALTER TABLE [dbo].[AspNetUsers]
ADD [LockoutEnd] DATETIMEOFFSET(7) NULL
GO
ALTER TABLE [dbo].[AspNetUsers]
ADD [NormalizedEmail] NVARCHAR(256) NULL
GO
ALTER TABLE [dbo].[AspNetUsers]
ADD [NormalizedUserName] NVARCHAR(256) NULL
GO
DROP INDEX [UserNameIndex] ON [dbo].[AspNetUsers];
GO
UPDATE [dbo].[AspNetUsers]
SET [NormalizedEmail] = UPPER([Email]), [NormalizedUserName] = UPPER([UserName])
GO
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
PRINT N'Creating [dbo].[AspNetUsers].[EmailIndex]...';
GO
CREATE NONCLUSTERED INDEX [EmailIndex]
ON [dbo].[AspNetUsers]([NormalizedEmail] ASC);
GO
PRINT N'Creating [dbo].[AspNetUsers].[UserNameIndex]...';
GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
ON [dbo].[AspNetUsers]([NormalizedUserName] ASC);
GO
PRINT N'Creating [dbo].[AspNetRoleClaims]...';
GO
CREATE TABLE [dbo].[AspNetRoleClaims] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ClaimType] NVARCHAR (MAX) NULL,
[ClaimValue] NVARCHAR (MAX) NULL,
[RoleId] NVARCHAR (128) NOT NULL,
CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
PRINT N'Creating [dbo].[AspNetRoleClaims].[IX_AspNetRoleClaims_RoleId]...';
GO
CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId]
ON [dbo].[AspNetRoleClaims]([RoleId] ASC);
GO
PRINT N'Creating [dbo].[AspNetUserTokens]...';
GO
CREATE TABLE [dbo].[AspNetUserTokens] (
[UserId] NVARCHAR (128) NOT NULL,
[LoginProvider] NVARCHAR (128) NOT NULL,
[Name] NVARCHAR (450) NOT NULL,
[Value] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [Name] ASC)
);
GO
PRINT N'Creating [dbo].[FK_AspNetUserClaims_AspNetUsers_UserId]...';
GO
ALTER TABLE [dbo].[AspNetUserClaims] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
GO
PRINT N'Creating [dbo].[FK_AspNetUserLogins_AspNetUsers_UserId]...';
GO
ALTER TABLE [dbo].[AspNetUserLogins] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
GO
PRINT N'Creating [dbo].[FK_AspNetUserRoles_AspNetRoles_RoleId]...';
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE;
GO
PRINT N'Creating [dbo].[FK_AspNetUserRoles_AspNetUsers_UserId]...';
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
GO
PRINT N'Creating [dbo].[FK_AspNetRoleClaims_AspNetRoles_RoleId]...';
GO
ALTER TABLE [dbo].[AspNetRoleClaims] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE;
GO
PRINT N'Checking existing data against newly created constraints';
GO
ALTER TABLE [dbo].[AspNetUserClaims] WITH CHECK CHECK CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId];
ALTER TABLE [dbo].[AspNetUserLogins] WITH CHECK CHECK CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId];
ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId];
ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId];
ALTER TABLE [dbo].[AspNetRoleClaims] WITH CHECK CHECK CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId];
GO
PRINT N'Update complete.';

column does not exist is postgresql

Here is my sql data.
When I execute this query in postgresql getting some error.
Please help me to correct this. I have no experience in this database.
-- ----------------------------
-- Sequence structure for tuning_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "mainpage"."tuning_id_seq";
CREATE SEQUENCE "mainpage"."tuning_id_seq" INCREMENT 1 START 4000 MAXVALUE 9223372036854775807 MINVALUE 1 CACHE 1;
ALTER TABLE "mainpage"."tuning_id_seq" OWNER TO "postgres";
-- ----------------------------
-- Table structure for tuning
-- ----------------------------
DROP TABLE IF EXISTS "mainpage"."tuning";
CREATE TABLE "mainpage"."tuning" (
"id" int4 NOT NULL DEFAULT nextval("tuning_id_seq"::regclass),
"motor_id" int4,
"speed" int4,
"freetext" varchar(200) COLLATE "default",
"date_create" varchar(30) COLLATE "default",
"date_change" varchar(30) COLLATE "default"
)
WITH (OIDS=FALSE);
ALTER TABLE "mainpage"."tuning" OWNER TO "postgres";
-- ----------------------------
-- Records of tuning
-- ----------------------------
BEGIN;
INSERT INTO "mainpage"."tuning" VALUES ('1', '1', '0', null, null, null);
INSERT INTO "mainpage"."tuning" VALUES ('2', '2', '0', null, null, null);
INSERT INTO "mainpage"."tuning" VALUES ('3', '3', '0', null, null, null);
COMMIT;
Error
NOTICE: table "tuning" does not exist, skipping
ERROR: column "tuning_id_seq" does not exist
********** Error **********
ERROR: column "tuning_id_seq" does not exist
SQL state: 42703
I think the issue is you need to schema-qualify your sequence name.
e.g.:
CREATE TABLE "mainpage"."tuning" (
"id" int4 NOT NULL DEFAULT nextval("mainpage"."tuning_id_seq"::regclass),
"motor_id" int4,
"speed" int4,
"freetext" varchar(200) COLLATE "default",
"date_create" varchar(30) COLLATE "default",
"date_change" varchar(30) COLLATE "default"
)
WITH (OIDS=FALSE);
ALTER TABLE "mainpage"."tuning" OWNER TO "postgres";
Without the qualification, Postgres will look for the sequence in the public (e.g. unqualified) schema. (Since you could, in theory, have a sequence by the same name in each schema).

some sequences not in dump from pg_dump

I want to pg_dump my database and have the problem that some sequences are generated in the dump file and some are not.
With the table infrastruktur_pictures it works with the table hoehenprofile it doesn't work. Here are the infos about the tables from pgadmin3:
hoehenprofile
CREATE SEQUENCE "hoehenprofile_HID_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 14289
CACHE 1;
ALTER TABLE "hoehenprofile_HID_seq";
CREATE TABLE hoehenprofile
(
"HID" serial NOT NULL,
hoehenprofil character varying(255),
CONSTRAINT "HID" PRIMARY KEY ("HID")
)
WITH (
OIDS=FALSE
);
ALTER TABLE hoehenprofile ADD COLUMN "HID" integer;
ALTER TABLE hoehenprofile ALTER COLUMN "HID" SET NOT NULL;
ALTER TABLE hoehenprofile ALTER COLUMN "HID" SET DEFAULT nextval('"hoehenprofile_HID_seq"'::regclass);
infrastruktur_pictures
CREATE SEQUENCE "infrastruktur_pictures_IPID_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
ALTER TABLE "infrastruktur_pictures_IPID_seq";
CREATE TABLE infrastruktur_pictures
(
"IPID" serial NOT NULL,
picture character varying(255) NOT NULL,
picture_text text,
fotograf text,
CONSTRAINT prim PRIMARY KEY ("IPID")
)
WITH (
OIDS=FALSE
);
ALTER TABLE infrastruktur_pictures ADD COLUMN "IPID" integer;
ALTER TABLE infrastruktur_pictures ALTER COLUMN "IPID" SET NOT NULL;
ALTER TABLE infrastruktur_pictures ALTER COLUMN "IPID" SET DEFAULT nextval('"infrastruktur_pictures_IPID_seq"'::regclass);
In the dump file the generated Code for hoehenprofile looks like this(no sequence is generated):
--
-- TOC entry 145 (class 1259 OID 67719)
-- Name: hoehenprofile; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE hoehenprofile (
"HID" integer DEFAULT nextval('"hoehenprofile_HID_seq"'::regclass) NOT NULL,
hoehenprofil character varying(255)
);
The code for infrastruktur_pictures looks like this:
-
-- TOC entry 152 (class 1259 OID 67750)
-- Name: infrastruktur_pictures; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE infrastruktur_pictures (
"IPID" integer NOT NULL,
picture character varying(255) NOT NULL,
picture_text text,
fotograf text
);
--
-- TOC entry 4230 (class 0 OID 0)
-- Dependencies: 152
-- Name: TABLE infrastruktur_pictures; Type: COMMENT; Schema: public; Owner: -
--
COMMENT ON TABLE infrastruktur_pictures IS 'Bilder im Infrastruktur Bereich des Backends';
--
-- TOC entry 153 (class 1259 OID 67756)
-- Name: infrastruktur_pictures_IPID_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE "infrastruktur_pictures_IPID_seq"
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- TOC entry 4231 (class 0 OID 0)
-- Dependencies: 153
-- Name: infrastruktur_pictures_IPID_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE "infrastruktur_pictures_IPID_seq" OWNED BY infrastruktur_pictures."IPID";
The only difference between this two tables i can see in pgadmin3. When i click on the specific cloumn(HID, IPID) in the object browser and look at the properties Tab right of it i can see that at the HID column the sequence attribute is not set.
The difference is that in the second case sequence is owned by table. Check last line of pg_dump.
This is because, when you create table using serial pseudo-datatype, the ownership is automatically added. But when you created sequence manually, you didn't set "OWNED BY".

Why can I not set this unique constraint in PostgreSQL?

I keep getting:
SQL error: ERROR: could not create
unique index
"service_import_checksum_key" DETAIL:
Key (checksum)=() is duplicated.
In statement:
ALTER TABLE "public"."service_import" ADD CONSTRAINT "service_import_checksum_key" UNIQUE ("checksum")
But this constraint ISN'T a duplicate. There is no other constraint like this anywhere in the entire database and I have no idea why on earth it keeps insisting it's a duplicate. I'm assuming this is some weird nuance of postgres that I'm missing here.
What am I doing wrong?
Table dump:
--
-- PostgreSQL database dump
--
SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = off;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET escape_string_warning = off;
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: service_import; Type: TABLE; Schema: public; Owner: cvs_tar; Tablespace:
--
CREATE TABLE service_import (
id integer NOT NULL,
name character varying(32) NOT NULL,
importfile character varying(64) NOT NULL,
reportfile character varying(64) NOT NULL,
percent smallint NOT NULL,
message text NOT NULL,
stamp timestamp without time zone DEFAULT now() NOT NULL,
complete smallint DEFAULT 0 NOT NULL,
checksum character varying(40) NOT NULL
);
ALTER TABLE public.service_import OWNER TO cvs_tar;
--
-- Name: service_imports_id_seq; Type: SEQUENCE; Schema: public; Owner: cvs_tar
--
CREATE SEQUENCE service_imports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.service_imports_id_seq OWNER TO cvs_tar;
--
-- Name: service_imports_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: cvs_tar
--
ALTER SEQUENCE service_imports_id_seq OWNED BY service_import.id;
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: cvs_tar
--
ALTER TABLE service_import ALTER COLUMN id SET DEFAULT nextval('service_imports_id_seq'::regclass);
--
-- Name: service_import_name_key; Type: CONSTRAINT; Schema: public; Owner: cvs_tar; Tablespace:
--
ALTER TABLE ONLY service_import
ADD CONSTRAINT service_import_name_key UNIQUE (name);
--
-- Name: service_import_pkey; Type: CONSTRAINT; Schema: public; Owner: cvs_tar; Tablespace:
--
ALTER TABLE ONLY service_import
ADD CONSTRAINT service_import_pkey PRIMARY KEY (id);
--
-- Name: service_import_complete_idx; Type: INDEX; Schema: public; Owner: cvs_tar; Tablespace:
--
CREATE INDEX service_import_complete_idx ON service_import USING btree (complete);
--
-- Name: service_import_stamp_idx; Type: INDEX; Schema: public; Owner: cvs_tar; Tablespace:
--
CREATE INDEX service_import_stamp_idx ON service_import USING btree (stamp);
--
-- PostgreSQL database dump complete
--
Read the error message again:
SQL error: ERROR: could not create unique index "service_import_checksum_key"
DETAIL: Key (checksum)=() is duplicated.
Looks like it is telling you that there are duplicate values in the checksum column and you're trying to enforce uniqueness on that column with your constraint. The constraint isn't duplicated, the data has duplicates.
Furthermore, the "()" part indicates that you have multiple empty strings in the checksum column. Unique constraints allow multiple NULL values (since NULL = NULL is NULL which is not true) but empty strings are not NULL.
An example to clarify what's going on:
=> CREATE TABLE x (s VARCHAR NULL);
CREATE TABLE
=> INSERT INTO x (s) VALUES (''), ('a'), ('');
INSERT 0 3
=> ALTER TABLE x ADD CONSTRAINT ux UNIQUE(s);
NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "ux" for table "x"
ERROR: could not create unique index "ux"
DETAIL: Key (s)=() is duplicated.
=> delete from x where s='';
DELETE 2
=> INSERT INTO x (s) VALUES ('a');
INSERT 0 1
=> ALTER TABLE x ADD CONSTRAINT ux UNIQUE(s);
NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "ux" for table "x"
ERROR: could not create unique index "ux"
DETAIL: Key (s)=(a) is duplicated.
In particular, note what the ERROR and DETAIL are saying and compare that to the INSERTs.