Frage Kann ich Ansichten mit Parametern in MySQL erstellen?


Ich habe eine Ansicht wie folgt:

CREATE VIEW MyView AS
   SELECT Column FROM Table WHERE Value = 2;

Ich möchte es generischer machen, es bedeutet, 2 in eine Variable zu verwandeln. Ich habe es versucht:

CREATE VIEW MyView AS
   SELECT Column FROM Table WHERE Value = @MyVariable;

Aber mysql erlaubt dies nicht.

Ich habe einen hässlichen Workaround gefunden:

CREATE FUNCTION GetMyVariable() RETURNS INTEGER DETERMINISTIC NO SQL
BEGIN RETURN @MyVariable; END|

Und dann ist zu sehen:

CREATE VIEW MyView AS
   SELECT Column FROM Table WHERE Value = GetMyVariable();

Aber es sieht wirklich beschissen aus, und die Verwendung ist auch beschissen - ich muss die @MyVariable vor jeder Verwendung der Ansicht einstellen.

Gibt es eine Lösung, die ich so verwenden könnte:

SELECT Column FROM MyView(2) WHERE (...)

Die konkrete Situation ist wie folgt: Ich habe eine Tabelle, in der Informationen zur abgelehnten Anfrage gespeichert werden:

CREATE TABLE Denial
(
    Id INTEGER UNSIGNED AUTO_INCREMENT,
        PRIMARY KEY(Id),
    DateTime DATETIME NOT NULL,
    FeatureId MEDIUMINT UNSIGNED NOT NULL,
        FOREIGN KEY (FeatureId)
            REFERENCES Feature (Id)
            ON UPDATE CASCADE ON DELETE RESTRICT,
    UserHostId MEDIUMINT UNSIGNED NOT NULL,
        FOREIGN KEY (UserHostId)
            REFERENCES UserHost (Id)
            ON UPDATE CASCADE ON DELETE RESTRICT,
    Multiplicity MEDIUMINT UNSIGNED NOT NULL DEFAULT 1,
    UNIQUE INDEX DenialIndex (FeatureId, DateTime, UserHostId)
) ENGINE = InnoDB;

Multiplizität ist die Anzahl identischer Anforderungen, die in derselben Sekunde aufgezeichnet werden. Ich möchte eine Liste der Verweigerungen anzeigen, aber manchmal, wenn die Anwendung abgelehnt wird, wiederholt es die Verbindungsversuche, um sicherzugehen. Wenn also derselbe Nutzer in ein paar Sekunden dreimal auf dieselbe Funktion geleugnet wird, ist dies in der Regel eine Ablehnung. Wenn wir eine weitere Ressource hätten, um diese Anfrage zu erfüllen, würden die nächsten beiden Dementis nicht passieren. Wir wollen also die Ablehnungen im Bericht gruppieren, damit der Benutzer die Zeitspanne angeben kann, in der Ablehnungen gruppiert werden sollen. Z.B. Wenn wir Dementis (für Benutzer 1 auf Feature 1) in Zeitstempeln haben: 1,2,24,26,27,45 und Benutzer Dementis gruppieren möchte, die dichter beieinander liegen als 4 Sekunden, sollte er etwa so aussehen: 1 (x2), 24 (x3), 45 (x1). Wir können annehmen, dass die Abstände zwischen realen Dementis viel größer sind als zwischen Duplikaten. Ich habe das Problem folgendermaßen gelöst:

CREATE FUNCTION GetDenialMergingTime()
    RETURNS INTEGER UNSIGNED
    DETERMINISTIC NO SQL
BEGIN
    IF ISNULL(@DenialMergingTime) THEN
        RETURN 0;
    ELSE
        RETURN @DenialMergingTime;
    END IF;
END|

CREATE VIEW MergedDenialsViewHelper AS
    SELECT MIN(Second.DateTime) AS GroupTime,
        First.FeatureId,
        First.UserHostId,
        SUM(Second.Multiplicity) AS MultiplicitySum
    FROM Denial AS First 
        JOIN Denial AS Second 
            ON First.FeatureId = Second.FeatureId
                AND First.UserHostId = Second.UserHostId
                AND First.DateTime >= Second.DateTime
                AND First.DateTime - Second.DateTime < GetDenialMergingTime()
    GROUP BY First.DateTime, First.FeatureId, First.UserHostId, First.Licenses;

CREATE VIEW MergedDenials AS
    SELECT GroupTime, 
        FeatureId,
        UserHostId, 
        MAX(MultiplicitySum) AS MultiplicitySum
    FROM MergedDenialsViewHelper
    GROUP BY GroupTime, FeatureId, UserHostId;

Um Dedizierungen von Benutzer 1 und 2 zu den Features 3 und 4 anzuzeigen, die alle 5 Sekunden zusammengeführt wurden, müssen Sie nur noch Folgendes tun:

SET @DenialMergingTime := 5;
SELECT GroupTime, FeatureId, UserHostId, MultiplicitySum FROM MergedDenials WHERE UserHostId IN (1, 2) AND FeatureId IN (3, 4);

Ich benutze Ansicht, weil es in es einfach ist, Daten zu filtern und explizit in jQuery Grid zu verwenden, automatisch zu bestellen, Anzahl der Datensätze zu begrenzen und so weiter.

Aber es ist nur ein hässlicher Workaround. Gibt es einen richtigen Weg, dies zu tun?


76
2018-02-17 15:25


Ursprung


Antworten:


Eigentlich wenn Sie func erstellen:

create function p1() returns INTEGER DETERMINISTIC NO SQL return @p1;

und sehen:

create view h_parm as
select * from sw_hardware_big where unit_id = p1() ;

Dann können Sie eine Ansicht mit einem Parameter aufrufen:

select s.* from (select @p1:=12 p) parm , h_parm s;

Ich hoffe, es hilft.


121
2018-03-16 21:09



CREATE VIEW MyView AS
   SELECT Column, Value FROM Table;


SELECT Column FROM MyView WHERE Value = 1;

Ist die richtige Lösung in MySQL, können Sie mit einigen anderen SQL-Ansichten Ansichten genauer definieren.

Hinweis: Wenn die Ansicht nicht sehr kompliziert ist, wird MySQL dies problemlos optimieren.


18
2018-02-17 15:47



Ich habe zuvor eine andere Problemumgehung gefunden, die keine gespeicherten Prozeduren verwendet, sondern stattdessen eine Parametertabelle und etwas connection_id () magic verwendet.

EDIT (von Kommentaren kopiert)

Erstellen Sie eine Tabelle, die eine Spalte namens enthält connection_id (mach es zu einem Bigint). Platzieren Sie Spalten in dieser Tabelle für Parameter für die Ansicht. Setzen Sie einen Primärschlüssel auf die connection_id. In die Parametertabelle ersetzen und verwenden CONNECTION_ID() um den connection_id-Wert aufzufüllen. Verwenden Sie in der Ansicht eine Kreuzverbindung zur Parametertabelle und setzen Sie sie WHERE param_table.connection_id = CONNECTION_ID(). Dies wird sich mit nur einer Zeile aus der Parametertabelle kreuzen, die das ist, was Sie wollen. Sie können dann die anderen Spalten in der where-Klausel zum Beispiel where verwenden orders.order_id = param_table.order_id.


1
2018-04-06 17:20