Announcement

Collapse
No announcement yet.

die WHERE Bedingung aus einem SQL-String extrahieren

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • die WHERE Bedingung aus einem SQL-String extrahieren

    Hallo,

    ich habe ein größeres Problem. Ich übergebe in meinem VB.Net-Programm SQL-Strings an eine Methode und benötige daraus die WHERE-Bedingung. An sich ja kein Problem. Man sucht nach WHERE und schneidet alles vorher weg und kickt dann ggf. noch das ORDER BY weg.
    Nun hab ich aber SQL-Strings dabei, die haben in den JOIN Anweisungen auch noch ein WHERE drin stehn und/oder in der WHERE-Bedingung noch SubSelects die ebenfalls das Wörtchen WHERE beinhalten können.
    Kennt jemand einen sicheren Weg, genau die WHERE-Bedingung aus dem String zu extrahieren?

    Beispielstring:

    SELECT dbo.TM_Warenpos.*.Gebiet, dbo.TM_Benennungen.Benennung, dbo.TS_Warenpos.*, dbo.TM_Warenpos.MaterialID AS MaterialPosID, dbo.TM_Benennungen.SprachKZ, dbo.TM_Benennungen.ObjektArt AS objektart_ben FROM dbo.TM_Warenpos INNER JOIN dbo.TS_Warenpos ON dbo.TM_Warenpos.MaterialID = dbo.TS_Warenpos.MaterialID LEFT OUTER JOIN dbo.TM_Benennungen ON dbo.TM_Warenpos.MaterialID = (SELECT dbo.TM_Benennungen.ObjektID From dbo.TM_Benennung WHERE dbo.TM_Benennungen.ObjektArt = 'M') WHERE dbo.TM_Benennung.SprachKZ = (SELECT SprachKZ FROM TM_Mitarbeiter WHERE MitarbName='ICH') ORDER BY TM_Warenpos.MaterialID


    Den grünen Teil würde ich hier zb. benötigen.
    Ich hab aber auch sehr einfache Strings auf die die Methode dann auch passen müsste.
    Ich komme da einfach auf keinen grünen Zweig

  • #2
    Hallo Andreas,

    vielleicht hilft dir die Methode 'Split' weiter.
    Hier ein Beispiel:

    Code:
    Dim command As String = "SELECT blablabla"
    command.Split(New String() {"WHERE"}, StringSplitOptions.None)
    *-- robert.oh. --*

    Comment


    • #3
      du könntest dir vielleicht einen Satz von regulären Ausdrücken zurechtlegen und wenn ein Ergebnis bei allen deinen Expressions dabei ist muss es das richtige sein. KÖnnte mir gut vorstellen dass so zu machen. In einer Datei abgelegt wärst du flexibel auf neue nicht getestete Fälle schnell zu reagieren.
      Unsere Jugend ist unerträglich, unverantwortlich und entsetzlich anzusehen! - Aristoteles

      Comment


      • #4
        Wenn ich das richtig verstehe, benötigst du die letzte Where-Bedingung.
        Dann such doch von hinten nach Where....

        Comment


        • #5
          Das war auch mein erster Gedanke, aber dort oder dahinter könnte in einem SubSelect noch ein Where enthalten sein (wie in seinem Beispiel). Deshalb reicht das Andreas noch nicht, und die Klammern gibt es nicht immer. Jürgen

          Comment


          • #6
            Problem hier ist doch, das "Ende" des where zu definieren. Das Finden mit split o.a. sollte kein Problem darstellen, aber welche Bedingungen beenden das where? Ein order? Ein beliebiges SQL Statement?
            Christian

            Comment


            • #7
              Solange du die möglichen SQL Select Strings nicht auf eine einfachere Grundmenge als die Gesamtmenge reduzieren kannst in der die Position eindeutig bestimmbar ist wirst du um einen echten SQL Parser nicht herumkommen.

              Ich glaube es wäre besser vorher anzusetzen. Heißt wieso hast du schon einen zusammengesetzen SQL String wenn du denn nachher wieder auseinander nimmst? Kannst du bei dem Problem nicht früher ansetzen so das du das Problem des ~auseinandernehmens müssens~ erst gar nicht hast?

              Comment


              • #8
                Die SQL Strings kommen teilweise aus XML-Dateien, wo sie der Kunde selber anlegen kann. D.h. er kann dort die wundersamsten Dinge anlegen.

                Ich habe mir über das Wochenende überlegt, ob es vielleicht funktioniert im String nach dem nächsten WHERE zu suchen und dann zu schauen, ob es sich innerhalb einer Klammer befindet. Dies würde anzeigen, das es sich um ein Subselect innerhalb eines Joins handeln muss. Ist dies nicht der Fall, hab ich das "echte" WHERE gefunden und müsste dann nur noch das letzte ORDER BY rauswerfen und schon hätte ich mein WHERE-Statement inkl. evtl. vorhandener SubSelects.

                Ich glaube die Split-Methode ist an dieser Stelle dann leider eher ungeeignet.

                Über RegEx hab ich auch nachgedacht, aber davon hab ich zu wenig bis keine Ahnung um so ein Szenario abzubilden.

                Comment


                • #9
                  Bedenke

                  - ORDER BY könnte auch in einem Subselect stecken
                  - WHERE, ORDER BY, Klammern etc. könnten auch in einer Stringkonstante stecken und gar nicht zum Syntax gehören.
                  - Filterbedingungen stehen nicht nur in der WHERE Klausel sondern in der ON Klausel eines JOINs.
                  - Es könnten Teile des Filters auch in der HAVING Klausel stehen
                  - Subselects müssen nicht zwingend geklammert sein. Ich glaube zum Beispiel beim Syntax mit ALL, ANY, SOME gehts auch ohne.
                  - Subselects könnten mehrfach geschachtelt sein
                  - Was machst du bei UNION/UNION ALL wen du da mehrere WHERE Klauseln hast?
                  - Es gibt bestimmt Leute die Tabellen anlegen die [WHERE] heissen.

                  Das ist was mir so auf Anhieb einfällt
                  Wenn du die Art der Statements nicht einschränken kannst wirst du ohne SQL Parser nicht glücklich werden

                  Comment


                  • #10
                    hmm..
                    Filterbedingungen der JOINs interessieren mich nicht, von daher kann ich die vernachlässigen.
                    Aber ob ein SubSelect ungeklammert funktioniert? Bin ich mir jetzt nicht sicher.
                    Und wer hingeht und seine Tabelle [WHERE] nennt, ist selber schuld wenn nix mehr geht

                    Ein weiterer Ansatz war jetzt, den String auf seine Klammern zu analysieren und alles was zwischen den Klammern steht zu ignorieren und bei dem ungeklammerten WHERE angekommen dann ein Split zu machen.
                    Aber wenn es zutrifft, das ein SubSelect nicht zwangsweise geklammert sein muss, dann hab ich echt gelitten.

                    Von SQL Parsern hab ich keine Ahnung. Gibt es da was ordentliches?

                    Comment


                    • #11
                      Einen empfehlenswerten Parser habe ich gerade nicht zur Hand. Habe selbst nur mal einen benutzt(in seligen Delphi Tagen) um die im Statement verwendeten Felder und Tabellen zu ermitteln. Da das ein kontextfreies Problem war ging das damals relativ einfach. Den benutzen Parser gibt es aber nicht mehr und du brauchst ja eh einen für .NET. Kann dich nur auf Google verweisen.

                      Aber wenn es zutrifft, das ein SubSelect nicht zwangsweise geklammert sein muss, dann hab ich echt gelitten.
                      Laut dem BNF zu SQL92 scheinen Subselects doch immer Klammern zu gehören.
                      Muß ich wohl falsch in Erinnerung gehabt haben.

                      Code:
                      <subquery>    ::=   <left paren> <query expression> <right paren>

                      Comment


                      • #12
                        ich habs der einfachheithalber mal ausprobiert. Ohne Klammern funktioniert es nicht

                        Comment


                        • #13
                          es hat jetzt etwas gedauert aber jetzt habe ich einen Algoritmus entwickelt, der mir die Position meines WHERE zurückgibt, so dass ich dort den String splitten kann.

                          [highlight=vb.net]
                          Public Function F_GetTrennPosition(ByVal zeile As String, ByVal trennz As String) As Integer
                          Dim klammerList As ArrayList = New ArrayList()
                          Dim trennPos As Integer = -1
                          Dim erstesZeichen As String = trennz.Substring(0, 1)

                          For i As Integer = 0 To zeile.Length - 1
                          Dim c As Char = zeile(i)
                          If c = "(" Then
                          klammerList.Add("(")
                          ElseIf c = ")" Then
                          klammerList.Remove("(")
                          End If

                          If klammerList.Count = 0 And (c = erstesZeichen.ToLower() Or c = erstesZeichen.ToUpper()) And i + trennz.Length < zeile.Length Then
                          Dim subString As String = zeile.Substring(i, trennz.Length)

                          If subString.ToLower() = trennz.ToLower() Then
                          trennPos = i
                          Exit For
                          End If
                          End If

                          Next
                          Return trennPos
                          End Function
                          [/highlight]

                          zeile beinhaltet den SQL-String
                          trennz beinhaltet (in meinem Fall) das Wort "WHERE"

                          Mit dem Code lassen sich aber auch zb. FROM und ORDER BY finden, also halt so ziemlich alles, was nicht geklammert ist.

                          Comment


                          • #14
                            Hi Andreas,

                            Der Ansatz ist schon mal gut. Jetzt brauchen wir noch eine Liste aller Keywords die nach dem WHERE kommen können, vor allem quer durch alle SQL Dialekte (damit alle was davon haben) , z.B. GROUP BY, ORDER BY, HAVING, FOR FETCH ONLY, FETCH FIRST x ROWS ONLY, WITH UR.

                            Mehr fallen mir auf die Schnelle nicht ein. Ich weiß nicht welche das in Deinem Fall wären, denn sonst ist Dein Ergebnis nicht die WHERE Bedingung an sich, sondern eben auch alles folgende.

                            Gruß Womble
                            < Der trotzdem begeistert ist >

                            Comment


                            • #15
                              in meinem Fall hab ich es an dieser Stelle einfach, da hier nur ORDER BY vorkommt
                              Wenn aber mal jemand eine wirklich umfassende Liste hat dürfte es nicht schwer sein zb. mit einem FOREACH alle Fälle duchzutesten, denke ich.

                              Comment

                              Working...
                              X