2009-08-13 9 views
1

Erstens bin ich mir nicht sicher, das ist der beste Weg, um dies mit allem umzugehen ... völlig offen für alternative Lösungen.SQL flattening & dynamische Abfrage Frage

Zweitens, ich fühle mich wie ich vermisse das offensichtliche ... aber ich vermisse es immer noch so nicht zu stolz zu fragen!

UPDATE: .NET 3.5 Umgebung w/SQL 2005, so dass Dinge wie dynamische Linq möglich, obwohl ich immer an dynamische (Build on Fly) Anfragen aller Art als Art von klobig denke. PITA zu pflegen.

UPDATE 2: Als Antwort auf Nordpol, Pseudo-Code/geschriebenes Wort Logik/SQL/Linq/C# akzeptabel ... mehr von einem fiktiven "was ist ein guter Ansatz" als I-Code Art müssen (!) der Frage.

eine Tabelle von "Schuhe" gegeben, die wie folgt aussieht:

 
    ShoeID PropertyName PropertyValue 
    1  COLOR   RED 
    2  COLOR   RED 
    2  SIZE   11 
    3  COLOR   RED 
    3  SIZE   11 
    3  MANUFACTURER GUCCI 

ich einen Weg (e) müssen für Schuhe abzufragen, so dass

COLOR = RED

 
    1 
    2 
    3 
zurück

FARBE = ROT und GRÖSSE = 11 ergibt

COLOR = ROT und SIZE = 11 und HERSTELLER = kehrt GUCCI

 
    3 

Zur Design-Zeit ich weiß nicht, wie viele verschiedene Eigenschaften, dass es sein könnte, und ich weiß nicht, wie viele Abfrageparameter könnte es sei ...

Hoffentlich macht das Sinn ... wenn nicht, bitte Kommentar entsprechend und ich werde es erneut versuchen.

+0

suchen Sie nach Abfrage Beispielen oder Datenbankstruktur Vorschläge? – northpole

+0

Suchen Sie direkt Ihre Datenbank oder verwenden Sie eine Programmiersprache? Welche SQL-Plattform verwenden Sie? SQL Server? MySQL? –

Antwort

0

Dynamische sql wird Ihnen helfen. Etwas wie:

ALTER PROCEDURE [dbo].[sp_GetFilteredRecords] 
(
... 
@ConditionList nvarchar(MAX) = null 
) 
AS 
BEGIN 
    DECLARE @sql  nvarchar(MAX), 
      @paramlist nvarchar(MAX) 

    SELECT @sql = 'select ... ' 
    ... 
    SELECT @sql = @sql + ' where 1=1 ' 
    ... 
    SELECT @sql = @sql + ' ' + @ConditionList + ' ' 


    SELECT @paramlist = ... 

    EXEC sp_executesql @sql, @paramlist 

Sicher kann es leicht aufgrund von Tools abweichen.

Boris.

+1

zusammen zu verketten dynamisches SQL ist in der Regel eine schlechte Idee - es ist fehleranfällig, anfällig für SQL-Injektion und umständlich zu verwenden. Da es sehr dynamisch ist, wird es normalerweise auch keine Indizes verwenden und daher langsam sein. Ich würde empfehlen, es zu verwenden, wann immer möglich –

+0

also, was Sie in dieser Situation vorschlagen können? eine andere Lösung? – Boris

0

Wenn ich Sie richtig verstehe, möchten Sie in der Lage sein, eine Abfrage zu erstellen, die Kriterien basierend auf einer beliebigen Anzahl von Feldern haben könnte, die im Voraus unbekannt sind. Das ist hart ....

Während die meisten RDBMS eine Art von "Dynamic SQL" -Fähigkeit bieten, neigen diese Ansätze dazu, entweder schwerfällig zu sein, oder langsam oder beides.

Natürlich könnten Sie auch eine SQL-Anweisung in Ihrem Client-Code verketten, sei es C#, Java, PHP oder was auch immer - aber das wird wiederum umständlich sein, anfällig für SQL-Injection-Angriffe und im Allgemeinen eher ungeschickt .

Auch wenn Sie Abfragen haben, die sich von einer Anforderung zu einer anderen unterscheiden, kann das RDBMS keine Ihrer Abfragepläne zwischenspeichern, und die Indizierung richtig zu bekommen, um eine anständige Abfrageleistung zu erhalten, wird bestenfalls herausfordernd sein. schlimmstenfalls unmöglich.

Also während ich die Anforderung vollständig verstehe (und fast täglich selbst abwehren muss), ist es wirklich etwas, das nicht gut funktioniert.Ich würde eher versuchen, die am häufigsten verwendeten Suchen und ihre Kriterien zu identifizieren und sicherzustellen, dass diese gut funktionieren und schnell sind. Beschränken Sie die Flexibilität des Benutzers, um eine anständige Abfrageleistung zu erzielen. Eine klassische Abwägung - Sie können völlig flexibel sein, aber dann haben Sie eine schreckliche Leistung, oder Sie können Ihre häufigen Abfragen schnell laufen lassen - aber etwas Flexibilität verlieren.

Ein Bereich, wo Sie möglicherweise etwas gewinnen können, ist bei der Suche nach freiem Text in Textfeldern - RDBMS wie SQL Server unterstützen das Konzept einer Volltextsuche, die Ihnen einige Flexibilität und gute Leistung gibt. Überprüfen Sie das, wenn Sie viele Textfelder haben.

Marc

+0

Hallo Marc - Höre dich laut und klar, aber nicht tun ist keine Option. Nur gute Nachrichten, wenn es welche gibt, ist, dass SQL-Injektion Angriff ist kein Problem! privat, keine UI etwas. – brmore

+0

Nun, Brad - Sie wurden gewarnt! :-) –

+0

Ha, jawohl .. ich habe! Arbeiten auch an einigen Alternativen. Tatsächlich haben Anforderungen nicht völlig verstanden, und es kann in Wirklichkeit nicht mehr eine "Datenbank" Sache sein. Es kann dazu führen, dass relativ kleine (10-100) EAV-Zeilen in ein Dictionary geladen werden und dann die Schnittstellen von Dictionaries manipuliert werden. Jawohl. – brmore

1

Also, ob dies ist ein bester Ansatz hängt von vielen Dingen. Müssen Sie beispielsweise verschiedene Objektklassen (z. B. Schuhe oder Kleider) unterstützen, die unterschiedliche (inkompatible) Attribute haben können? Oder wie hoch ist die geschätzte Anzahl an Entitäten, die Sie haben werden (etwas, das für 10K einigermaßen gut funktioniert, wird für 100M nicht funktionieren)? Oder wie oft müssen Sie mit solchen Anfragen umgehen und wie gut müssen sie leisten?

Zwei gängige Denkschulen sind EAV model, die mehr oder weniger das ist, was Sie haben und column-based approach wo die Eigenschaften Ihrer Entität (Farbe, Größe, etc ...) jeweils einer separaten Spalte zugeordnet sind. Jede hat ihre Vor- und Nachteile, die größte von ihnen ist die Flexibilität/Leistung der ersteren und die Notwendigkeit, die Tabellenstruktur für letztere dynamisch zu verändern.

Wenn Sie mit Ihrem vorhandenen Modell gehen, würde ich empfehlen, Ihre Eigenschaftsnamen in eine separate Tabelle zu verschieben und die Schuh-Tabelle zu ändern, um FK zu dieser Tabelle zu haben. Anschließend können Sie einen Index auf (property_id, shoe_id) erstellen und Abfragen erzeugen, wie folgt:

SELECT shoe_id FROM shoes S_1 [, shoes S_2, ..., shoes S_X] 
WHERE S_1.property_id = 3 /* FK for 'color' */ 
    /* the following 3 lines will be repeated for each 'property' you need to query on */ 
    AND S_X.property_id = 4 /* FK for 'size' */ 
    AND S_X.shoe_id = S_1.shoe_id 
    AND S_X.property_value = 'RED' 

die führen sollte vernünftigerweise gut, vorausgesetzt, Sie haben eine mehr oder weniger gleichmäßige Verteilung von Attributen und nicht eine große Anzahl von Schuhe.