2011-02-23 12 views
5

Ben almaya devamBu benzersiz kısıtlamayı PostgreSQL'de neden ayarlayamıyorum?</p> <blockquote> <p>SQL error: ERROR: could not create unique index "service_import_checksum_key" DETAIL: Key (checksum)=() is duplicated.</p> </blockquote> <p>açıklamada:

ALTER TABLE "public"."service_import" ADD CONSTRAINT "service_import_checksum_key" UNIQUE ("checksum")

Ama bu kısıt yinelenen DEĞİLDİR. Tüm veritabanında bunun gibi başka bir kısıtlama yoktur ve yeryüzünde niçin bir kopya olduğu konusunda ısrar ettiği konusunda hiçbir fikrim yoktur. Sanırım burası kayıp olan postgreslerin garip bir nüansı.

Neyi yanlış yapıyorum?

Tablo dökümü:

-- 
-- 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 
-- 
+0

Bize "CREATE TABLE" ifadesini tamamlayabilir veya tablonun başka bir açıklamasını verebilir misiniz? Ayrıca, "BENZERSİZ İNDEX OLUŞTUR" yerine çalışır? – Charles

cevap

14

tekrar hata mesajı okuyun: sizi anlatıyor gibi

SQL error: ERROR: could not create unique index "service_import_checksum_key" DETAIL: Key (checksum)=() is duplicated.

checksum sütunda çift değer olduğunu görünüyor ve eşsizliği güçlendirmek için çalışıyoruz kısıtlama ile o sütunda. Kısıtlama çoğaltılmamış, verilerin kopyaları var.

Ayrıca, "()" bölümü, checksum sütununda birden çok boş dizeye sahip olduğunuzu gösterir. Benzersiz kısıtlamalar, birden çok NULL değerine izin verir (NULL = NULL, NULL, bu doğru değildir) ancak boş dizeler NULL değildir.

örneği

neler netleştirmek için: Özellikle

=> 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. 

, HATA ve DETAY söylediklerini not ve ınsert'ler ile karşılaştırabilirsiniz.

+1

Bu, geliştiricilerin hile yapmasını önlemek için ek bir kontrol kısıtlaması gereksiniminin en iyi örneğidir. Alan NULL değil, ancak işaretlenmemiş bir dizedir, bu yüzden boş bir dizeyi NOT NULL kısıtlaması atlatmak için koyuyorlar. Benim krallık SQL standardına bir ekleme için "boş" dizeleri (herhangi bir uzunlukta) engelleyen bir dize türü. –

+1

@Matthew Wood: Kontrol toplamının istenen uzunluğa (daha fazla, daha az değil) sahip olduğundan ve sadece sağlama toplamı için yalnızca geçerli karakterler içerdiğinden emin olmak için açık bir CHECK kısıtlaması kullanmalıyım; sağlama toplamı muhtemelen sabit boyutlu bir hex değeridir ve geliştiriciler gerektiğinde sıfırlayabilir. Tüm boş dizgeyi boş bırakacağız çünkü boş_string doğru ve benim ORMim başka bir gün için aptallığı fark etmek için çok aptal :) Ben DBA değilim ama bunu biliyorum '' ve NULL farklı şeyler veritabanının dışında bile. –

+0

Hakkında: "Benzersiz kısıtlamalar çoklu NULL değerlerine izin verir (NULL = NULL yanlıştır) ancak boş dizeler NULL değildir." DING! Başarmak. Hepsi sabit. Aptal şey, sütunu oluşturduğumda boş dizelerde otomatik doldurma oldu ve oradan indeksi eklemek imkansızdı. –

İlgili konular