Posso creare una vista con parametro in MySQL?

Ho una vista come questa:

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

Mi piacerebbe renderlo più generico, significa cambiare 2 in una variabile. Ho provato questo:

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

Ma mysql non lo consente.

Ho trovato una brutta soluzione:

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

E poi la vista è:

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

Ma sembra davvero schifoso, e l’utilizzo è anche schifoso – Devo impostare @MyVariable prima di ogni utilizzo della vista.

C’è una soluzione, che potrei usare in questo modo:

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

La situazione concreta è la seguente: Ho una tabella che memorizza informazioni sulla richiesta negata:

 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; 

La molteplicità è il numero di richieste identiche registrate nello stesso secondo. Voglio visualizzare un elenco di smentite, ma a volte, quando l’applicazione viene negata, riprova un paio di volte solo per essere sicuro. Di solito, quando lo stesso utente rifiuta 3 volte la stessa funzione in pochi secondi, in realtà è un rifiuto. Se avessimo una risorsa in più, per soddisfare questa richiesta, i prossimi due dinieghi non accadranno. Pertanto, desideriamo raggruppare i dinieghi nel rapporto che consentono all’utente di specificare l’intervallo di tempo in cui i dinieghi dovrebbero essere raggruppati. Ad esempio, se abbiamo smentite (per l’utente 1 sulla funzione 1) in data e ora: 1,2,24,26,27,45 e l’utente vuole raggruppare le smentite più vicine tra loro di 4 s, dovrebbe ottenere qualcosa di simile a questo: 1 (x2), 24 (x3), 45 (x1). Possiamo supporre che gli spazi tra smentite reali siano molto più grandi che tra duplicazioni. Ho risolto il problema nel modo seguente:

 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; 

Quindi per mostrare i dinieghi dagli utenti 1 e 2 sulle funzionalità 3 e 4 unite ogni 5 secondi tutto quello che devi fare è:

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

Io uso view, perché in esso è facile filtrare i dati e usarli esplicitamente nella griglia jQuery, ordinare automaticamente, limitare il numero di record e così via.

Ma è solo una brutta soluzione. C’è un modo corretto per farlo?

In realtà se crei func:

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

e visualizza:

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

Quindi puoi chiamare una vista con un parametro:

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

Spero possa essere d’aiuto.

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

È la soluzione corretta in MySQL, alcuni altri SQL ti consentono di definire le viste in modo più preciso.

Nota: a meno che View non sia molto complicato, MySQL ottimizzerà questo aspetto.

In precedenza ho trovato una soluzione alternativa che non utilizza stored procedure, ma utilizza invece una tabella dei parametri e alcuni magic_id_connessione ().

EDIT (copiato dai commenti)

crea una tabella che contenga una colonna chiamata connection_id (rendilo un bigint). Posiziona le colonne in quella tabella per i parametri per la vista. Metti una chiave primaria su connection_id . sostituire nella tabella dei parametri e utilizzare CONNECTION_ID() per popolare il valore connection_id. Nella vista utilizzare un cross join alla tabella dei parametri e inserire WHERE param_table.connection_id = CONNECTION_ID() . Questo attraverserà il join con una sola riga dalla tabella dei parametri che è ciò che vuoi. È quindi ansible utilizzare le altre colonne nella clausola where, ad esempio, dove orders.order_id = param_table.order_id .