Jump to content

hh2000

Members
  • Gesamte Inhalte

    550
  • Registriert seit

  • Letzter Besuch

Alle erstellten Inhalte von hh2000

  1. hh2000

    MSSQL Abfrage - Max

    Moin, das gibt leider nur eine Zeile zurück, da die Unterabfrage nur eine Zeile liefert (den MaxWert von ItemValue der gesamten Tabelle). Die Unterabfrage muss mit der Hauptabfrage korrelieren, z.B. so: SELECT a.Datum, a.ItemValue, a.Uhrzeit FROM tblTest a INNER JOIN ( SELECT Datum, MAX(ItemValue) AS maxIV FROM tblTest GROUP BY Datum ) b ON a.Datum = b.Datum AND a.ItemValue = b.maxIV Die "Tabelle b" (eigentlich eine Abfrage) liefert den MaxWert pro Datum. Dieses Hilfskonstrukt dient der Auswahl der entsprechenden Datensätze (Max(ItemValue) pro Datum). Durch den JOIN mit der "Tabelle a" können aber nun auf alle Spalten in "Tabelle a" zugegriffen werden. Gruß Kai
  2. Moin, der Befehl heißt SELECT (Transact-SQL). Hier ist für Dich das WHERE ("BisDatum" von <= 01.01.2005) wichtig und zum verbinden der beiden Tabellen "INNER JOIN ... ON ... ". Die Tabellen sollten über einen Foreign Key verbunden sein um referentielle Integrität zwischen beiden herzustellen CREATE TABLE (Transact-SQL) . Bevor du allerdings ein Löschkommando absetzt, solltest Du Dich tiefer in die Materie einarbeiten, sonst kann es sehr schnell passieren das mit nur einem Befehl alles weg ist. Gruß Kai
  3. Moin, Ja, schau mal in der Online Hilfe nach den Stichworten ODBC, Querydef, Recordset. Du kannst auch einen Access-View als SQL-Pass-Through definieren (mit den korrekten Verbindungsparametern), der dann z.B. als Inhalt ein "EXEC Prozedur para1, para2" enthält. Gruß Kai
  4. Moin, ein bischen was zum einlesen zum Thema Backup-Server, hier ein paar Informationen zum Log Shipping: LogShipping Überblick How to Perform SQL Server Log Shipping - SQL Server Performance Ist teilweise etwas älter, aber interessant. Gruß Kai
  5. Es muss in Access eine Fehlerbehandlung implementiert sein, um den RAISERROR abzufangen. Da du den Code nicht anfassen willst, solltest du im Log-Trigger Datum und Username (oder wird hier mit nur einem zentralen User gearbeitet?) mitprotokollieren, vielleicht reicht das ja an Information. z.B. Tabelle.User = SUSER_SNAME(), Tabelle.Zeit = CURRENT_TIMESTAMP Du könntest auch mit einer mdE statt einer mdB arbeiten, dann sollte RAISERROR einen Fehler melden, aber der client macht anschließend weiter. Das sind nur Workarounds. Besser ist es, eine Fehlerbehandlung einzubauen. Access: On Error Goto .... SQL: RAISERROR Gruß Kai
  6. Moin, ich kenne das auch so, dass man nicht NULL als Wert einfügen darf. Die Online-Hilfe sagt ja auch: "DEFAULT, Gibt den Wert an, der für die Spalte bereitgestellt wird, wenn kein Wert explizit angegeben wurde. " Meint, Du darfst eben keinen Wert für die Spalte angeben. Ein einfügen von NULL ist ungleich "kein Wert", sondern versucht ausdrücklich diese Spalte mit NULL zu füllen und daher wird nicht der DEFAULT-Wert benutzt. Gruß Kai
  7. Moin, PRINT geht nicht, RAISERROR ist hier Dein Freund. Wie Dukel schon schrieb, per Delete-Trigger die "Löschungen" protokollieren und bei Beschwerden über fehlenende Daten, Logtabelle durchsuchen. Gruß Kai
  8. Moin, ich würde erstmal testweise ein Update-Command direkt im Query Analyser abschicken, um evlt. Sperrungen o.a. die der Client auslösen könnte, auszuschliessen. Sollte das Problem dann immer noch auftauchen, so würde ich auch erstmal den Trigger vermuten. Du könnstest dann statt des AFTER-Triggers, einen INSTEAD OF-Trigger benutzen. Deine Änderungen/Exporte in eine Log-Tabelle etc. kannst mit Hilfe von Inserted und Deleted anfertigen. Anschließend must Du aber selbst dafür sorgen (im Unterschied zum AFTER-Trigger), dass die gewünschten Werte in Deine Tabelle eingetragen werden. CREATE TRIGGER TabelleUpd ON [dbo].[Tabelle] INSTEAD OF UPDATE AS -- Hier Deine Statements, Transcaction, Fehlerbehandlung etc -- Alte Werte sind in deleted enthalten und könnten in eine LogTabelle geschrieben werden UPDATE Tabelle SET Tabelle.SpalteA = inserted.SpalteA, Tabelle.SpalteB = inserted.SpalteB Tabelle.UpdateUser = SUSER_SNAME(), Tabelle.UpdateZeit = CURRENT_TIMESTAMP FROM Tabelle INNER JOIN inserted ON Tabelle.ID = inserted.ID END Mittels @@ERROR und RAISERROR (siehe Onlinehilfe) in den SQL Statements kannst du dann auch den Fehler besser eingrenzen, bzw. ausgeben. Gruß Kai
  9. Moin, das funktioniert so nicht mit den Unions. In dem Beispiel werden werden einige Zeilen doppelt im Ergebenis auftauchen (WHERE-Bedingungen sind nicht exakt) Übersichtlicher, ressourcensparender ist das mit CASE zu lösen. Für den MS-SQL-Server könnte das so aussehen (TRUE ist 1, FALSE ist 0 in einer Spalte vom Typ bit): SELECT Kulanz, Mindermenge, Gewicht, PreisproKg, Summe = CASE WHEN Kulanz = 1 THEN 0 WHEN Mindermenge = 1 THEN PreisproKg ELSE Gewicht * PreisproKg END FROM Tabelle Gruß Kai
  10. Hallo, ich würde die Tabellen nicht anfassen, bzw. die IDENTITY-Spalte weglassen. Wenn nur 2 Tabellen mittels UNION zu verknüpfen sind, könntest du bei einer Tabelle die ID von -1 absteigend erzeugen lassen. Das das wohl aber nicht der Fall sein wird, würde ich beim Erzeugen des UNION eine neue eindeutige Spalte erzeugen. Kommt ein bischen auf die Daten und auf das Format an, was du zur Weiterverarbeitung brauchst, z.B.: SELECT ID, ... FROM TabA UNION SELECT ID * 100000, ... FROM TabB ... oder SELECT 'A' + CAST(ID AS varchar) AS ID, ... FROM TabA UNION SELECT 'B' + CAST(ID AS varchar), ... FROM TabB ... Gruß Kai
  11. Hallo, das sollte klappen: UPDATE Exemplar SET Spalte = LEFT(Spalte, CHARINDEX(';', Spalte, CHARINDEX(';', Spalte)+1)) WHERE Spalte LIKE '%;%;%' Das innerste CHARINDEX findet das erste Semikolon (Position). Auf diese Position wird eine 1 addiert und dem zweiten CHARINDEX als Startwert der Suche übergeben. Nun findet das zweite CHARINDEX die Position des zweiten Semikolon, das nun an LEFT übergeben wird. LEFT bildet dann den neuen String. Wichtig: mit WHERE muss(!) garantiert werden, dass die zu ändernden Strings auch mindestens 2 Semikolon enthalten, sonst gibt es leere Spalten. CHARINDEX (Transact-SQL) Am besten erstmal mit SELECT testen: SELECT LEFT(Spalte, CHARINDEX(';', Spalte, CHARINDEX(';', Spalte)+1)) FROM Exemplar WHERE Spalte LIKE '%;%;%' Gruß Kai
  12. hh2000

    SQL Count Abfrage

    Moin, SELECT * FROM BJobs INNER JOIN BSession ON BJobs.JobID = BSession.JobID WHERE BJobs.LastestResult <> 0 AND BJobs.JobName = 'daily' AND BSession.EndTime > DATEADD(DAY, -1, Getdate() ) Für andere zeitliche Einschränkungen siehe Onlinehilfe DATEADD, GetDate(), CURRENT_TIMESTAMP Gruß Kai
  13. Moin, so könnte das aussehen: SELECT * FROM T_Tabelle WHERE FileID IN ( SELECT FileID FROM T_Tabelle WHERE Value = 1 AND BlaBla = Wert1 ) AND FileID IN ( SELECT FileID FROM T_Tabelle WHERE Value = 2 AND BlaBla = Wert1 ) AND FileID IN ( SELECT FileID FROM T_Tabelle WHERE Value = 3 AND BlaBla = Wert1 ) Du hast soviele Unterselects wie du Suchbedingungen hast oder soviele (Selbst-)Verknüpfungen wie Suchbedingungen: SELECT FileID FROM T_Tabelle a INNER JOIN T_Tabelle b ON a.FileID = b.FileID INNER JOIN T_Tabelle c ON a.FileID = c.FileID WHERE (a.Value = 1 AND a.BlaBla = Wert1) AND (b.Value = 2 AND b.BlaBla = Wert1) AND (c.Value = 3 AND c.BlaBla = Wert1) (Klammern dienen nur der Lesbarkeit) Gruß Kai
  14. Moin, arbeite immer mengenbasiert, daher streiche mal alle Variablen. Es kann keiner, einer, oder viele Sätze gleichzeitig eingefügt/updated werden, das ist immer zu berücksichtigen. z.B. (ID ist hier eindeutig, IDENTITY (Autowert)): Im INSERT Trigger: INSERT INTO testtabelle (name) SELECT name FROM inserted Im UPDATE Trigger: UPDATE testtabelle SET testtabelle.name = inserted.name, testtabelle.Altername = deleted.name FROM testtabelle INNER JOIN inserted ON testtabelle.id = inserted.id INNER JOIN deleted ON testtabelle.id = deleted.id Gruß Kai
  15. Hallo, Kleine Korrektur, der Insert-Trigger arbeitet genauso wie der Update- und Delete-Trigger, also mengenbasiert: INSERT INTO Tabelle1 (SpalteA, SpalteB) SELECT SpalteA, SpalteB FROM Tabelle2 Hier wird der Trigger nur einmal ausgelöst. Das funktioniert so nicht wie gewünscht: Generell beim Trigger immer beachten: a) Es wird kein Datensatz zurückgeliefert (@Benutzer wäre dann NULL) b) Es wird genau EIN Datensatz geliefert (@Benutzer = 'ABC', Super, Programm funktioniert) c) Es werden mehrere Datensätze geliefert (@Benutzer = ?? ) Daher muss Dein Programm diese Fäle alle abdecken können, sonst geht es schief. Gruß Kai
  16. Moin, falls Ihr den Ansprechpartner nicht braucht, lasst ihn doch einfach weg oder wenn die Spalte gewünscht wird, dann nimm eine Konstante wie 'APName' AS Ansprechpartner. Den ersten Anprechpartner den die Abfrage findet, bekommst du sonst mit einer korrelierenden Unterabfrage (Bei jeder Zeile der Hauptabfrage wird hier die Unterabfrage ausgeführt). z.B. SELECT KundenID, (SELECT TOP 1 APName FROM T_AP WHERE T_AP.KundenNr = T_Kunden.KundenID) FROM T_Kunden Gruß Kai
  17. Moin, So sollte das klappen: SELECT MitarbeiterID, DAY(StartDatum), SUM(DATEDIFF(n, StartDatum, EndDatum)) AS Minuten FROM T_Zeiten WHERE Startdatum >= '01.01.2011' AND Startdatum < '01.02.2011' GROUP BY MitarbeiterID, DAY(StartDatum) Gruß Kai
  18. Der Weg über Variablen ist so leider nicht korrekt (was soll in @DeletePK enthalten sein, wenn 2 Sätze gleichzeitig geändert werden ?). Du musst ggf. die Tabellen inserted, deleted, TableOrg passend joinen. Dabei solltest Du in einem Trigger immer berücksichtigen, dass a) kein Satz b) ein Satz c) oder mehrere Sätze upgedated werden könnten. z.B.: UPDATE TableOrg SET Gewicht=inserted.gw1 FROM TableOrg INNER JOIN inserted ON TableOrg.IDNr = inserted.IDNr Vorausgesetzt Deine Tabelle die den Trigger enthält und TableOrg enthalten die gleichen Datensätze mit den gleichen IDNrn, so wird der geänderte Wert auch in TableOrg geändert. Gruß Kai
  19. hh2000

    Update Trigger

    Hallo, Das ist der Befehl der ausgeführt wird, der updated halt alle Sätze :-) Du musst Deinen Update-Befehl mit der Tabelle "inserted" (siehe auch Online-Hilfe: "inserted", "deleted") joinen, z.B.: UPDATE dbo.Transponder SET GeändertAm = CURRENT_TIMESTAMP FROM dbo.Transponder INNER JOIN inserted ON dbo.Transponder.ID = inserted.ID Im Update-Trigger werden so nur die geänderten Sätze aktualisiert. Gruß Kai
  20. Moin, kurze Version der Vorgehensweise: - Trigger erstellen der auf "Update" reagiert - Im Trigger Daten z.B. aus der Tabelle "deleted" verwenden. - Die gewünschten Werte per INSERT INTO in eine 2. Tabele eintragen. Weiterführende Stichworte für die Hilfe im SQL-Server: CREATE TRIGGER, deleted, inserted, INSERT INTO Gruß Kai
  21. Moin, um einem User an einer Prozedur das Ausführen Recht zu gewähren führst Du folgendes SQL-Statement aus: (hier z.B. für die Rolle public): USE msdb GRANT EXECUTE ON dbo.sp_send_dbmail TO public Alternativ über den Manager die Prozedur suchen - Eigenschaften - Berechtigungen - dort die entsprechenden Haken setzen. Ob das jetzt bei System-Prozeduren die korrekte Vorgehensweise ist oder ob es gerade für Mail-Profile eine andere Vorgehensweise gibt, weiß ich leider nicht. Gruß Kai
  22. hh2000

    Frage zu Abfrage

    Moin, noch ein kleiner Tipp, versuch soviel Daten wie möglich schon im "WHERE" statt im "HAVING" einzugrenzen, das bringt bei größeren Datenmengen bessere Performance (wenn SQL >2000 das nicht sowieso von allein optimiert). Warum gruppiert Du nach Menge? Da möchtest Du doch die Summe bekommen. Oder habe ich hier etwas übersehen? z.B.: SELECT Artikel, LEFT(Periode, 4) AS Jahr, SUM(Menge) AS [summe Menge] FROM dbo.Tabelle WHERE (Menge > 0.000) AND (LEFT(Periode, 4) = '2009') GROUP BY Artikel, LEFT(Periode, 4) Gruß Kai
  23. Moin, wie lange braucht den das Update-Statement wenn Du es allein laufen lässt ? Kannst Du das o.g. Problem auf dieses Update-Statement eingrenzen, bzw. bleibt dieses Update beim ausführen schon "hängen" ? (Stichwort: Ausführungsplan, Indizes) Gruß Kai
  24. Ja teste mal bitte SP4. (Datensicherung, Hersteller Einverständnis ok?) Ich hatte bei einem ähnlichem Problem auf einer 2-Prozessormaschiene ohne SP4, als Workaround SQL auf einen Prozessor beschränken müssen. Allerdings war im SQL-Server Protokoll ein Hinweis darauf zu finden (etwas mit "Parallelism", "Deadlock", genauen Text hab ich nicht mehr). Dort wurde auch eine geschachtelte Abfrage u.a. mit Join auf sich selbst auf verschiedene Threads verteilt, die sich dann gegenseitig blockierten, aber eben nicht bei allen Werten. Du kannst evtl. zum testen die Abfrage auch mit MAXDOP "optimieren". max degree of parallelism Option SELECT Spalte(n) FROM Table OPTION (MAXDOP 1) Die Ausstattung war NT4 mit SQL 2000 SP3, SP4 war dort nicht möglich. Gruß Kai EDIT: ich war zu langsam ....
  25. Moin, ich würde ggf. den SQL-String etwas verschlanken (HAVING). So z.B. (weiß aber nicht ob das Deine Anforderung abdeckt, hier wird nur der ältere Doppelte angezeigt, Dein Beispiel bringt wohl alle Doppelten zur Anzeige?): SELECT kunde.Name, kunde.Strasse, kunde.Hausnr, kunde.Ort, kunde.Werbecode, kunde.Datensatz, kunde.StandortKz, kunde.PromotorNr, importiertam FROM kunde WHERE kunde.[iD] In (SELECT MIN([iD]) FROM [kunde] As TMP2 WHERE [TMP2].[Dublette] is null and [TMP2].[werbecode] = 'Stern 2010' GROUP BY [Name],[strasse],[Hausnr],[Ort],[Werbecode] HAVING Count(*)>1 ) ORDER BY kunde.Name, kunde.Strasse, kunde.Hausnr, kunde.Ort, kunde.Werbecode,LfdNr Welches Service Pack (SQL) ist installiert (SELECT @@VERSION)? Gruß Kai
×
×
  • Neu erstellen...