AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Column "xxx" specified more than once
Thema durchsuchen
Ansicht
Themen-Optionen

Column "xxx" specified more than once

Ein Thema von Incocnito · begonnen am 13. Mär 2020 · letzter Beitrag vom 17. Apr 2020
Antwort Antwort
Seite 2 von 2     12   
Incocnito

Registriert seit: 28. Nov 2016
210 Beiträge
 
#11

AW: Column "xxx" specified more than once

  Alt 17. Apr 2020, 15:20
Ich habe da mal was gebaut, mit dem das jeder nachvollziehen könnte.
Man muss natürliche eine PostgreSQL-Datenbank haben und eine neue Datenbank samt Benutzer anlegen.

Delphi-Quellcode:
unit TemporaererTestGF;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.ExtCtrls, Vcl.StdCtrls, Uni;

{
-- Table: test_sh.fam_pruefung

-- DROP TABLE test_sh.fam_pruefung

CREATE TABLE test_sh.fam_pruefung
(
    bemerkung text COLLATE pg_catalog."default",
    charge character varying(20) COLLATE pg_catalog."default",
    data text COLLATE pg_catalog."default",
    pruefungsdatum date,
    herstellungsdatum date,
    lfdnr integer,
    massnahme text COLLATE pg_catalog."default",
    pruefer character varying(5) COLLATE pg_catalog."default",
    pzn integer,
    status integer,
    verfalldatum date
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE test_sh.fam_pruefung
    OWNER to testuser;

GRANT ALL ON TABLE test_sh.fam_pruefung TO testuser;
GRANT ALL ON TABLE test_sh.fam_pruefung TO postgres;
}


type
  TfrmTemporaererTestGF = class(TForm)
    btnRun: TButton;
    pnlButtons: TPanel;
    btnClose: TButton;
    procedure btnCloseClick(Sender: TObject);
    procedure btnRunClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  frmTemporaererTestGF: TfrmTemporaererTestGF;

implementation

uses
  DB;

{$R *.dfm}

procedure TfrmTemporaererTestGF.btnCloseClick(Sender: TObject);
begin
  Close();
end;

procedure TfrmTemporaererTestGF.btnRunClick(Sender: TObject);
var
  xnPZN : Integer;
  nLfdNr : Integer;
  APFAMPRU_SQL : TUniTable;
  DBCon : TUniConnection;
begin
  DBCon := TUniConnection.Create(nil);
  DBCon.ProviderName := 'PostgreSQL';
  DBCon.Options.LocalFailover := True;
  DBCon.SpecificOptions.Add('ApplicationName=TestGF');

  DBCon.Database := 'test_db';//DBGloApo.FDConnection.Database;
  DBCon.Username := 'testuser';//DBGloApo.FDConnection.Username;
  DBCon.Password := 'test_12345';//DBGloApo.FDConnection.Password;

  DBCon.Server := 'localhost';//DBGloApo.FDConnection.Server;
  DBCon.Port := 9999;//DBGloApo.FDConnection.Port;
  DBCon.Connected := True;

  APFAMPRU_SQL := TUniTable.Create(Application.MainForm);
  APFAMPRU_SQL.Connection := DBCon;

  APFAMPRU_SQL.TableName := 'test_sh.fam_pruefung';//TPostgres.SchemaNameAposoft + '.' + 'fam_pruefung';

  APFAMPRU_SQL.OrderFields := 'PZN, Pruefungsdatum';
  APFAMPRU_SQL.Open();

  try
    APFAMPRU_SQL.OrderFields := 'LfdNr';
    APFAMPRU_SQL.Last();
    nLfdNr := APFAMPRU_SQL.FieldByName('LfdNr').AsInteger + 1;
    APFAMPRU_SQL.OrderFields := 'PZN, Pruefungsdatum';

    // ----

    xnPZN := 9206022;

    if (APFAMPRU_SQL.Locate('PZN', VarArrayOf([xnPZN]), [])) then
    begin
      APFAMPRU_SQL.Filter := 'PZN = ' + xnPZN.ToString;
      APFAMPRU_SQL.Filtered := True; // <- Diese Zeile ist das Problem!?
      APFAMPRU_SQL.Execute(); // Mit Execute geht alles!
      APFAMPRU_SQL.Filtered := False;
      APFAMPRU_SQL.Execute(); // Mit Execute geht alles!
    end;

    APFAMPRU_SQL.Append();
    APFAMPRU_SQL['PZN'] := xnPZN;
    APFAMPRU_SQL['Pruefungsdatum'] := EncodeDate(2020, 4, 3);
    APFAMPRU_SQL['Charge'] := '111';
    APFAMPRU_SQL['Herstellungsdatum'] := EncodeDate(2020, 1, 1);
    APFAMPRU_SQL['Verfalldatum'] := EncodeDate(2020, 12, 31);
    APFAMPRU_SQL['Status'] := 1;
    APFAMPRU_SQL['Pruefer'] := 'gfr';
    APFAMPRU_SQL['LfdNr'] := nLfdNr;
    APFAMPRU_SQL.Post();
  finally
    try APFAMPRU_SQL.Free(); except end;
    try DBCon.Free(); except end;
  end;
end;

end.
Hatte ich mein Tabellen-Objekt also beim Filtern um das Execute erweitert,
lief alles problemlos. Ein wenig seltsam finde ich das aber schon.
Vor allem, dass es so ein bisschen geht.
1) Wenn "Verfalldatum" klein geschrieben ist (nur das Rest ist egal)
2) Nach Filtern mit "Execute"

PS: Nicht wie ich darauf reinfallsen: Beim ersten Mal läuft es ja, weil er das Filtern nicht ausführt!
PS2: Den Port und evtl. den Server müsst ihr natürlich auch für euch anpassen!

PS3: Leider habe ich keine Zeit dem weiter nachzugehen.
Falls mal jemand etwas ähnliches hat, hilft dieser Trick aber ja.

LG Incocnito
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.139 Beiträge
 
Delphi 12 Athens
 
#12

AW: Column "xxx" specified more than once

  Alt 17. Apr 2020, 15:53
Zitat:
Wenn "Verfalldatum" klein geschrieben ist
Normal ist in Postgre die Groß-/Kleinschreibung egal, so lange ein Name nicht in " angegeben wurde.

Es wird automatisch ein Lowercase über alles gelegt, außer bei 'Strings' und "Namen" mit " .

Zitat:
Das macht meiner Meinung nach bei einer einzelnen Tabelle bzw. bei einem Append keinen Sinn.
Ja, es gibt einmal den Fall, dass die Spalte bei einem JOIN in mehreren Tabellen/Quellen vorhanden ist und man hier den Namespace (Tabellenname) mit angeben muß, damit die DB weiß was du eigentlich willst.

Und dann gibt es den Fall, dass eine Spalte mehrfach im Select vorkommt, z.B. nochmal mit AS umbenannt.

SELECT aaa, aaa AS bbb oder bei SELECT aaa, * bzw, SELECT aaa AS bbb, * .

Hier gibt es erstmal kein Problem, aber wenn das Feld geändert wurde und man das POSTen will, dann weiß die DBKompoente nicht welchen Wert die nun speichern soll.
Den Wert von aaa oder den von bbb, welcher ja auch in aaa gespeichert würde.

Lösung:
  • Entweder die Extended-Infos der DB-Komponente deaktivieren, also damit PgDAC/UniDAC/... nicht weiß dass bbb eigentlich aaa ist
  • oder auf Seiten der DB bereits diese Verbindung auftrennen, indem man das Feld durch eine Funktion jagt
    SELECT aaa, Trim(aaa) AS bbb, Coalsece(aaa, NULL) AS ccc, EineEigeneDetachFunctionDamitManAmNamenErkenntWarumDasHierSteht(aaa) AS ddd .
  • oder manuell ein Insert- und Update-Statement in der DB-Komponente hinterlegen, damit nicht versucht wird automatisch Eines zu generieren



Wie UniDAC hier nun clientseitig arbeitet .... wer weiß, aber vermutlich auch so wie PgDAC, welches die Vegleiche der Namen case-insensitiv durchführt,
womit clientseitig das eigentlich auch egal wäre.


Hast du mal nachgesehn, wie es in der Datnbank aussieht?
Wurden die Felder Verfalldatum oder Status dort eventuell wirklich explizit mit Großschreibung erstellt?



PS: Bei nur einem Feld, wäre beim Locate der Weg über das Variant-Array nicht nötig.
APFAMPRU_SQL.Locate('PZN', VarArrayOf([xnPZN]), ...) = APFAMPRU_SQL.Locate('PZN', xnPZN, ...)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (17. Apr 2020 um 16:19 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz