我可以在 MySQL 中创建带参数的视图吗?

我有这样一个观点:

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

我想把它变得更通用,它的意思是把2变成一个变量,我试过这样做:

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

但 MySQL 不允许这样做。

我发现了一个难看的解决办法:

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

接下来的观点是:

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

但是它看起来真的很糟糕,而且用法也很糟糕——我必须在每次使用视图之前设置@Myvariable。

有没有这样的解决办法:

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

具体情况如下: 我有一个存储有关被拒绝请求的信息的表:

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;

多重性是在同一秒内记录的许多相同的请求。我想显示一个拒绝列表,但有时,当应用程序被拒绝时,它会重试几次以确保。因此,通常情况下,当同一个用户在几秒钟内在同一个功能上被拒绝3次时,实际上是一次拒绝。如果我们还有一个资源,来满足这个要求,接下来的两次拒绝就不会发生了。因此,我们希望在报告中将拒绝分组,允许用户指定拒绝分组的时间跨度。例如,如果我们有拒绝(对于功能1上的用户1)的时间戳: 1,2,24,26,27,45和用户想要组拒绝接近彼此超过4秒,他应该得到这样的东西: 1(x2) ,24(x3) ,45(x1)。我们可以假设,真实否认之间的空间要比复制之间的空间大得多。我用以下方法解决了这个问题:

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;

然后,为了显示用户1和2对特性3和特性4的否认,每5秒钟合并一次,你需要做的就是:

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

我使用这个视图是因为它很容易过滤数据,并在 jQuery 网格中显式地使用它,自动排序,限制记录数量等等。

但这只是一个丑陋的变通方案。有没有合适的方法来做到这一点?

146002 次浏览
CREATE VIEW MyView AS
SELECT Column, Value FROM Table;




SELECT Column FROM MyView WHERE Value = 1;

Is the proper solution in MySQL, some other SQLs let you define Views more exactly.

Note: Unless the View is very complicated, MySQL will optimize this just fine.

Actually if you create func:

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

and view:

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

Then you can call a view with a parameter:

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

I hope it helps.

I previously came up with a different workaround that doesn't use stored procedures, but instead uses a parameter table and some connection_id() magic.

EDIT (Copied up from comments)

create a table that contains a column called connection_id (make it a bigint). Place columns in that table for parameters for the view. Put a primary key on the connection_id. replace into the parameter table and use CONNECTION_ID() to populate the connection_id value. In the view use a cross join to the parameter table and put WHERE param_table.connection_id = CONNECTION_ID(). This will cross join with only one row from the parameter table which is what you want. You can then use the other columns in the where clause for example where orders.order_id = param_table.order_id.