AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken [PLSQL] Gibt es ein "Select oder Insert"- Befehl?
Thema durchsuchen
Ansicht
Themen-Optionen

[PLSQL] Gibt es ein "Select oder Insert"- Befehl?

Ein Thema von sirius · begonnen am 5. Jul 2010 · letzter Beitrag vom 7. Jul 2010
Antwort Antwort
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#1

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 00:00
@sirius

Irgendwie finde ich das ganze Konstrukt nicht so griffig.

Erzeuge doch alle Datensätze der Tabelle DBT_ZEIT im voraus. Das sind 876000 Datensätze einer sehr schmalen Tabelle für die nächsten 100 Jahre.

Damit sparst du dir
  • das Insert
  • die Sequenz
  • den Trigger
  • das abfangen der Exception dup_val_on_index

Das hat für die Robustheit und Performance der SP nur Vorteile und der Code wird auch übersichtlicher und damit auch verständlicher.

Geändert von HeZa ( 6. Jul 2010 um 05:12 Uhr) Grund: typo
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.829 Beiträge
 
Delphi 12 Athens
 
#2

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 08:23
Wenn Du Lücken vermeiden willst (das scheint sich als Hintergrund herauszukristallisieren), nutze nicht Sequences und Trigger, sondern vergib selber die ID.

Sherlock
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#3

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 08:54
Danke Euch für die Antworten,

@HeHa, ja in dem Fall könnte man das vielleicht sogar so lösen (weis nicht, ob das so üblich ist). Aber ich sagte ja, dass dies nur ein Beispiel unter vielen ist. Ich schreib halt immer wieder die selbe Befehlssequenz die da besteht aus
  • Ermitteln ob der Datanesatz schon vorhanden ist
  • Wenn ja, dann PK holen
  • Wenn nein dann Insert probieren
    • falls Insert fehl schlägt (Exception abfangen) dann PK von dem inzwischen eigentragenen Datensatz holen
Und das halt nicht nur bei dbt_Zeit, sondern auch für verschiedene andere Tabellen, wo das nicht so geht. (Ich wollt ja erst nicht ein Beispiel posten, weil ich schon erwartete, dass die Antworten dann zu konkret auf das Beispiel bezogen sind) Also nehmt das Beispiel nur als Beispiel. Ich wollt hier nur einmal wissen, wie andere Datenbanknutzer in ihren Projekten damit umgegangen sind (ich bin ja hoffentlich nicht der erste) und ob es zufällig sogar einen Befehl gibt in Oracle.

zu den Lücken: Lücken kann man nicht vermeiden, aber man muss ja nicht schon von vorn herein im Konzept ca. 10000 IDs überspringen.

@idefix2: Ja, der nächste Datensatz hätte einen neuen PK, aber alle anderen Werte wären gleich. Ich hätte somit einen überflüssigen Eintrag. Dies ist nicht gewünscht und wird meistens durch einen unique constraint verhindert.

@borwin: Danke für den Code. Behebt zwar nicht das urspüngliche Problem, aber beschleunigt meine bisherige Lösung.

Danke Euch allen für Eure Beiträge. Aber ich befürchte langsam, dass ich der einzige bin, der ständig über dieses Problem stolpert.

Edit: @Sherlock, Selber PK zu vergeben ist aber ziemlich riskant. Aber wie gesagt, ist nicht das eigentliche Problem.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#4

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 09:37
Ich schreib halt immer wieder die selbe Befehlssequenz die da besteht aus
  • Ermitteln ob der Datanesatz schon vorhanden ist
  • Wenn ja, dann PK holen
  • Wenn nein dann Insert probieren
  • falls Insert fehl schlägt (Exception abfangen) dann PK von dem inzwischen eigentragenen Datensatz holen

...

Ich wollt hier nur einmal wissen, wie andere Datenbanknutzer in ihren Projekten damit umgegangen sind (ich bin ja hoffentlich nicht der erste) und ob es zufällig sogar einen Befehl gibt in Oracle.

...

Danke Euch allen für Eure Beiträge. Aber ich befürchte langsam, dass ich der einzige bin, der ständig über dieses Problem stolpert.
Du bist bestimmt nicht der erste der dieses Muster verwendet. Du scheinst es aber als eine Art Standard Muster zu verwenden und das ist es nicht. Wir können uns natürlich nur auf dieses eine Beispiel beziehen. Ich bin mir fast sicher, das kein anderer hier die Sache so wie du lösen würde.

Die Tabelle DBT_ZEIT macht einen kranken Eindruck. Sie hat einen eindeutigen Schlüssel (Datum, Stunde) und du gibst ihr noch einen künstlichen warum? Warum überhaupt eine Tabelle DBT_ZEIT? Trage Datum und Stunde in DBT_Traffic ein und nimm sie mit in den Primary Key auf. Warum ein Datumsfeld und ein Stundenfeld wenn die Stunde doch mit in das Datumsfeld passt?

Übernehme nur das Datumsfeld in DBT_TRAFFIC (lösche ID_ZEIT) und fülle es mit ROUND(<Datum>, 'HH'). Das würde deine Inserts erheblich beschleunigen und deine SP würde nur aus dem MERGE und dem Signal senden bestehen.

Ich weiß ja nichts über die Update-Häufigkeit und die Datenmenge. Mein erster Ansatz wäre erstmal jeden Traffic-Datensatz mit dem genauen Zeitpunkt zuspeichern. Verdichtung würde ich erst für die Auswertung.

Für mich sieht deine Lösung etwas exotisch aus. Bring doch mal eine der anderen Stellen wo dieses Muster verwendest. Vielleicht kann man ja auch dort aufzeigen wie es einfacher, sicherer und schneller geht.

Geändert von HeZa ( 6. Jul 2010 um 09:39 Uhr) Grund: typo
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#5

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 10:12
Für mich sieht deine Lösung etwas exotisch aus. Bring doch mal eine der anderen Stellen wo dieses Muster verwendest. Vielleicht kann man ja auch dort aufzeigen wie es einfacher, sicherer und schneller geht.
Ok.
SQL-Code:
-- Die Tabelle dbt_Channel führt verschiedene IDs (alles FK) aus anderen Tabellen zusammen zu einem neuen einzigen Key.
-- Diese FKs bilden einen unique index (in anderen Varianten gab es noch zusätzliche Spalten, welche außerhalb jedweden Indexes lagen)
-- der PK (Spaltenname: ID), der hier in dbt_Channel gebildet wird, wird in verschiedenen Messwerttabellen verwendet, welche mit Abstand dann auch die größten Tabellen sind.

    Select count(ID) into c from dbt_channel
     where ID_Characteristic=CharacteristicID
     and ID_BaseIndicator=BaseIndicatorID
     and ID_Indicator=IndicatorID
     and ID_Phase=PhaseID
     and ID_Unit=UnitID
     and ID_Interval=IntervalID
     and Frequency=aFrequency;
    if c>0 then
      if aDoInsert then
        RaiseAlreadyExist('Channel');
      end if;
    else
      if not aDoInsert then
        RaiseNotExist('Channel');
      end if;
      begin
        insert into dbt_Channel (Id_Characteristic,Id_Phase,Id_Indicator,
                               id_Unit,Id_Interval,Frequency,Id_Baseindicator)
            values (CharacteristicID,
                    PhaseID,
                    IndicatorID,
                    UnitID,
                    IntervalID,
                    aFrequency,
                    BaseIndicatorID)

            returning ID into ChannelID;
        commit;
      exception
        when dup_val_on_index then
          c:=1;
        when others then
          raise;
      end;
    end if;
    if c>0 then
      Select ID into ChannelID from dbt_channel
       where ID_Characteristic=CharacteristicID
       and ID_BaseIndicator=BaseIndicatorID
       and ID_Indicator=IndicatorID
       and ID_Phase=PhaseID
       and ID_Unit=UnitID
       and ID_Interval=IntervalID
       and Frequency=aFrequency;
    end if;
    return(ChannelID);


   -- Die Reaktion auf aDoInsert ist hier nochmal gesondert zu sehen und muss nicht zwingend hier beachtet werden
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#6

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 10:26
Ok, ich habe es so gewollt .

Dann bitte aber auch noch die Beschreibung dieser Channel Tabelle und deren ungefähre Update-Häufigkeit (grob 10 pro Stunde oder tausende pro Minute oder gar Sekunde?).
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#7

AW: [PLSQL] Gibt es ein "Select oder Insert"- Befehl?

  Alt 6. Jul 2010, 10:41
SQL-Code:
prompt
prompt Creating table DBT_CHANNEL
prompt ==========================
prompt
create table DBT_CHANNEL
(
  ID NUMBER not null,
  ID_BASINDICATOR NUMBER not null,
  ID_INDICATOR NUMBER not null,
  ID_PHASE NUMBER not null,
  ID_UNIT NUMBER not null,
  ID_INTERVAL NUMBER not null,
  FREQUENCY NUMBER(*,2),
  ID_CHARACTERISTIC NUMBER not null
)
;
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_PK primary key (ID);
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_UK1 unique (ID_BASINDICATOR, ID_INDICATOR, ID_PHASE, ID_UNIT, ID_INTERVAL, FREQUENCY, ID_CHARACTERISTIC);
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_DBT_BASEINDIC_FK1 foreign key (ID_BASINDICATOR)
  references DBT_BASEINDICATOR (ID) on delete cascade;
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_DBT_CHARACTER_FK1 foreign key (ID_CHARACTERISTIC)
  references DBT_CHARACTERISTIC (ID);
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_DBT_INDICATOR_FK1 foreign key (ID_INDICATOR)
  references DBT_INDICATOR (ID) on delete cascade;
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_DBT_INTERVAL_FK1 foreign key (ID_INTERVAL)
  references DBT_INTERVAL (ID) on delete cascade;
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_DBT_PHASE_FK1 foreign key (ID_PHASE)
  references DBT_PHASE (ID) on delete cascade;
alter table DBT_CHANNEL
  add constraint DBT_CHANNEL_DBT_UNIT_FK1 foreign key (ID_UNIT)
  references DBT_UNIT (ID) on delete cascade;
Auf dem PK ID liegt wieder eine Sequence und ein Trigger (wie bei dbt_Zeit)

Ein neuer Eintrag kommt recht unregelmäßig. Zeit spielt hier nicht die oberste Rolle.


Ok, ich habe es so gewollt .
Ich hab das auch noch mit dynamischen SQL gelöst, welches mehrere solche Tabellen mit ähnlicher Tabellenstruktur (von den "wichtigen" Spalten her) bedient.

Und bitte wegrationalisiere mir meine ausnormalisierte Tabelle hier nicht weg
Es ist durchaus möglich, dass hier noch Spalten mit Zusatzinformationen ergänz werden
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.

Geändert von sirius ( 6. Jul 2010 um 10:45 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 07:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz