Frage

Ich habe eine vom Such gespeicherte Prozedur mit SQL Server 2005 geschrieben. Es werden eine Reihe von Parametern benötigt und die Suchkriterien sind mäßig komplex.

Aufgrund der Front-End-Architektur muss ich in der Lage sein, die Anzahl der Ergebnisse zurückzugeben, die zurückkommen würden ohne tatsächlich die Ergebnisse zurückgeben. Das vordere Ende würde dann das gespeicherte Verfahren ein zweites Mal aufrufen, um die tatsächlichen Ergebnisse zu erzielen.

Einerseits kann ich zwei gespeicherte Prozeduren schreiben - eine, um die Anzahl zu behandeln, und eine, um die tatsächlichen Daten zu verarbeiten, aber dann muss ich die Suchlogik an mindestens zwei verschiedenen Stellen beibehalten. Alternativ kann ich die gespeicherte Prozedur so schreiben, dass sie einen Bitparameter nimmt und basierend darauf entweder Daten zurückgegeben oder nur eine Anzahl. Möglicherweise füllen Sie eine temporäre Tabelle mit den Daten und wenn sie nur eine Zählung darstellt, zählen Sie ansonsten eine Auswahl daraus. Das Problem hierfür ist, dass der Zählerprozess optimiert werden könnte, so dass es viel zusätzliche Gemeinkosten ist (es scheint unnötige Spalten zu erhalten usw.). Die Verwendung dieser Art von Logik in einem gespeicherten Verfahren kann auch zu schlechten Abfrageplänen führen, da sie zwischen den beiden Verwendungen hin und her geht.

Die Datenmenge im System ist nicht zu hoch (nur ein paar Millionen Zeilen auch für größere Tabellen). Möglicherweise gibt es jedoch viele gleichzeitige Benutzer.

Was denken die Menschen zu diesen Ansätzen? Hat jemand dieses Problem zuvor auf eine Weise gelöst, an die ich nicht gedacht habe?

Sie KANN NICHT Nehmen Sie die Ergebnisse und zählen Sie gleichzeitig von einem einzigen Anruf.

Vielen Dank!

War es hilfreich?

Lösung

Ich persönlich gehe mit dem beiden Abfrageansatz an, ja, Sie müssen die Suchlogik an zwei Stellen beibehalten, aber ich habe festgestellt, dass sich die Leistungsoptimierung und die allgemeine Sauberkeit des Codes am Ende auszahlt.

Die Verwendung eines Flaggens an ein einzelnes Verfahren ist eine potenzielle Lösung, aber ich finde es nur sehr schwer zu warten, insbesondere für komplexe Suchlogik.

Die Route der Verwendung von temporären Tabellen usw., die nur viel mehr Overhead als das benötigt wird.

Warum bin ich also mit der beiden Abfragemethoden gelandet. Alles, was ich online finde, empfiehlt auch diesen Ansatz.

Andere Tipps

Dies ist kein normales Problem und Sie möchten normalerweise, dass die Gesamtzahlen gleichzeitig eine Seite erhalten.

Verwenden Sie jedoch zwei verschiedene Verfahren. Der Grund dafür ist, dass Sie zwei sehr unterschiedliche Aktionen haben, die sich nur oberflächlich ähneln.

Ich bin mir sicher, dass Sie dies in Betracht gezogen haben: Wenn die Daten die Anzahl ändern und nachfolgende tatsächliche Paging möglicherweise unterschiedlich sein (wenn die Zeilen hinzugefügt / entfernt werden)

Sie könnten eine benutzerdefinierte Funktion haben, die die PKs der übereinstimmenden Zeilen zurückgegeben hat, relativ einfach zu machen a

SELECT COUNT(*) FROM dbo.MyQueryFunction(@Param1, @Param2)

um die Zählung zu bekommen und dann

SELECT Col1, Col2, ...
FROM dbo.MyQueryFunction(@Param1, @Param2) AS FN
     JOIN dbo.MyTable AS T
         ON T.ID = FN.ID
     ... more JOINs ...

Um die Daten zu erhalten.

Ich weiß nicht, wie gut dies mit row_number für das nachfolgende Paging sitzt, aber es würde die tatsächliche "Abfragelogik" in MyQueryFunction halten - Sie werden immer noch alle Verknüpfungen für eine Spalte haben, die im SPROC abgerufen werden sollen und im Sproc und im Sproc und im SPROC abgerufen werden sollen. die Funktion.

Möglicherweise helfen Sie bei Ihrem spezifischen Problem nicht, aber SQL 2005 führt die Funktion row_number vor, die für die Paging -Prüfung praktisch ist

Zoub_number Beispiel

Viel einfacher als Tempel.

Ich fand diesen Thread, der etwas anderes recherchierte, und dachte, ich würde erwähnen, dass es möglich ist, das Ergebnis -Set und die Datensätze mit einer Abfrage zu zählen. Sie benötigen nur einen "Out" -Parameter, um den Wert zu tragen. Nachfolgend finden Sie eine Kopie/Einfügung eines Oracle -Beispiels, aber die Technik ist für SQL Server sehr ähnlich (ich habe keinen Zugriff auf SQL Server ATM).

Das große Ding mit SQL Server ist, dass Sie möglicherweise Row_Number () gegen Rownum verwenden müssen.

procedure get_sample_results (
    startrow in number default 1,
    numberofrows in number default 10,
    whereclause in varchar2,
    matchingrows out number,
    rc  out sys_refcursor
)
is
    stmnt varchar2(5000);
    endrow number;
begin

    stmnt := stmnt || 'select * from table t where 1=1';
    if whereclause is not null then
        stmnt := stmnt || ' and ' || whereclause;
    end if;

    execute immediate 'select count(*) from (' || stmnt || ')' into matchingrows;

    stmnt := 'select * from (' || stmnt || ') where rownum between :1 and :2';        

    -- must subtract one to compenstate for the inclusive between clause
    endrow := startrow + numberofrows - 1;
    open rc for stmnt using startrow, endrow;

end get_sample_results;

Ich weiß, dass dies eine alte Frage (die bereits gekennzeichnet wurde), aber Sie können ein Datensatz (auch bekannt als die Ergebnisse) zurückgeben und eine Ausgabe (oder mehrere Ausgabewerte) haben, was bedeutet, dass Sie nur eine Roundreise zur Datenbank benötigen.

Das ist etwas, was ich laut nachdenke (und es ist an meiner Schlafenszeit vorbei ...)

CREATE PROCEDURE WhatEver
(
   @SomeParam1 NVARCHAR(200),
   ....
   @SomeParam_X INT,
   @NumberOfResults INTEGER OUTPUT
)
BEGIN
    SET NOCOUNT ON

    -- Do your search stuff.
    -- ....
    SELECT Whatever
    FROM WhatWhat
    ...

    -- Ok, the results/recordset has been sent prepared.
    -- Now the rowcount
    SET @NumberOfResults = @@ROWCOUNT
END

HTH.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top