Zuerst, bitte verzeih mir, wenn ich die falschen Begriffe verwende, bin ich sehr neu sowohl PostgreSQL und NoSQL-style Datenspeicherung. Weiter:JSON-Spalte mit automatisch inkrementierendem Feld in Postgres einfügen?
Ich benutze npgsql, um ein .NET-Projekt mit einer PostgreSQL-Datenbank zu verbinden. Wir verwenden es als NoSQL-Dokumentenspeicher, wobei unsere Tabellen aus einem Primärschlüssel id
Spalte und einem Jsonb-Objekt in der Spalte data
bestehen, sonst nichts.
In der Spalte data
möchten wir auch eine Möglichkeit, ein ID-Feld zu generieren, das bei jedem Einfügen automatisch inkrementiert wird. Diese ID muss nicht unbedingt mit dem Primärschlüssel übereinstimmen, aber das ist die Annahme, von der ich arbeite.
Ich habe in der Lage gewesen, diese Arbeit in pgAdmin machen mit der folgenden Scripts:
drop table public.testjson;
drop sequence public.testjson_id_seq;
CREATE SEQUENCE public.testjson_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
ALTER TABLE public.testjson_id_seq
OWNER TO login;
CREATE TABLE public.testjson
(
id bigint NOT NULL DEFAULT nextval('testjson_id_seq'::regclass),
data jsonb,
CONSTRAINT testjson_pkey PRIMARY KEY (id)
);
ALTER TABLE public.testjson
OWNER TO login;
-- Insert data using currval --
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}'));
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}'));
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}'));
INSERT INTO testjson (data) VALUES(to_jsonb('{"jsonid": '||currval('testjson_id_seq'::regclass)::bigint||', moreStuff: "all the stuff!"}'));
select * from testjson
-- Output --
id | data
---------------------------------------------------------
1 | "{\"jsonid\": 1, moreStuff: \"all the stuff!\"}"
2 | "{\"jsonid\": 2, moreStuff: \"all the stuff!\"}"
3 | "{\"jsonid\": 3, moreStuff: \"all the stuff!\"}"
4 | "{\"jsonid\": 4, moreStuff: \"all the stuff!\"}"
So weit, so gut. Ich denke, ich werde dies umgestalten, so dass das Jsonid-Feld seine eigene Sequenz hat und nextval
anstelle von currval
verwendet (um Race-Bedingungen zu vermeiden, die zu Duplikaten führen), aber die Frage ist nicht darüber. Ich habe Probleme, dies auf der Codepage zu replizieren. Umsah in anderen questions hier führte mich zu glauben, dass dies funktionieren könnte:
var crcmd = new NpgsqlCommand("INSERT INTO "+_schema+"."+table+" ("+JsonColumn+") VALUES (:json) RETURNING id;", _conn);
var jsonData = getSerializedJsonData(thing, primaryKey);
crcmd.Parameters.AddWithValue("json", NpgsqlDbType.Jsonb, jsonData);
returnId = (long) crcmd.ExecuteScalar();
...
private string getSerializedJsonData<T>(T thing, string primaryKey, string tableSeq)
{
var jsonThing = JsonConvert.SerializeObject(thing);
var bracketIndex = jsonThing.IndexOf('{');
var thingPrefix = jsonThing.Substring(0, bracketIndex + 1);
var thingData = jsonThing.Substring(bracketIndex + 1);
var pkEntry = "\"" + primaryKey +"\": currval('" + tableSeq + '::regclass)::bigint, ";
jsonThing = thingPrefix + pkEntry + thingData;
return jsonThing;
}
Aber wenn ich versuche, es zu testen, wird die folgende Ausnahme ausgelöst:
Npgsql.PostgresException: 22P02: invalid input syntax for type json; Token "currval" is invalid
Irgendwelche Ideen, wo ich falsch liege?
Einfügen der Daten in die Abfrage direkt als ein String bricht die Grundregel von Datenbanken. Haben Sie jemals eine bessere Lösung gefunden? – piojo