QUESTION How can I create a MySQL table so, that a field's default value is the output of a function.
问题如何创建MySQL表,以便字段的默认值是函数的输出。
Can it be done without an insert trigger?
可以在没有插入触发器的情况下完成吗?
BACKGROUND: Some entities and the groups they belong to need to be observed on a daily basis.
背景:需要每天观察一些实体及其所属的群体。
To do that I created the following MySQL table:
为此,我创建了以下MySQL表:
CREATE TABLE entity (
entity_id VARCHAR(10) NOT NULL,
group_id VARCHAR(10) NOT NULL,
first_seen DATE NOT NULL,
last_seen DATE NOT NULL,
PRIMARY KEY (entity_id,group_id)
)
A script parses the entity logs on a daily basis and writes to to entity_raw, I then want to update the tables using
脚本每天解析实体日志并写入entity_raw,然后我想使用更新表
REPLACE INTO entity (entity_id,group_id,last_seen)
SELECT entity_id,group_id,record_date
FROM entity_raw
WHERE (record_date = DATE(DATE_SUB(NOW(),INTERVAL 1 DAY))
Naturally I get an error when inserting new (entity_id,group_id) pairs, since first_seen may not be NULL...
当然,插入新的(entity_id,group_id)对时会出错,因为first_seen可能不是NULL ...
Can this be done in one statement, short of using a trigger (I dislike them, too surprising for maintenance)
这可以在一个声明中完成,没有使用触发器(我不喜欢它们,太难以维护)
or do I need to select for existance first, then insert/update accordingly?
或者我是否需要先选择存在,然后相应地插入/更新?
4 个解决方案
#1
2
No, what you're asking isn't possible without triggers. The only example in MySQL where a field can be assigned a default value from a function is the TIMESTAMP type that can have CURRENT_TIMESTAMP as default.
不,没有触发器,你所要求的是不可能的。 MySQL中唯一可以为函数分配默认值的示例是TIMESTAMP类型,它可以将CURRENT_TIMESTAMP作为默认值。
#2
1
To be honest it's pretty much impossible to combine an update or insert into one statement.
说实话,将更新或插入组合成一个语句几乎是不可能的。
If you are using a script, I would do as you suggested. First check for existence, then update or insert accordingly.
如果您使用的是脚本,我会按照您的建议进行操作。首先检查是否存在,然后相应地更新或插入。
Otherwise a trigger or stored procedure would do the job.
否则,触发器或存储过程将完成这项工作。
#3
1
You could use the TIMESTAMP
data type, which allows a default value of CURRENT_TIMESTAMP
, but that would set it to NOW()
and not to a day ago.
您可以使用TIMESTAMP数据类型,它允许默认值CURRENT_TIMESTAMP,但这会将其设置为NOW()而不是前一天。
So, I would rather use use an INSERT... ON DUPLICATE KEY UPDATE
statement:
所以,我宁愿使用INSERT ... ON DUPLICATE KEY UPDATE语句:
INSERT INTO entity (entity_id,group_id,first_seen,last_seen)
SELECT entity_id,group_id,record_date, record_date
FROM entity_raw
WHERE (record_date = DATE(DATE_SUB(NOW(),INTERVAL 1 DAY))
ON DUPLICATE KEY UPDATE last_seen = VALUES(last_seen)
with a unique index en entity_id
and/or group_id
. This will overwrite only last_seen
when an existing row is found.
具有唯一索引en entity_id和/或group_id。当找到现有行时,这将仅覆盖last_seen。
#4
0
After some searching I came up with this .. it solves my "problem", but not the question I asked :-(
经过一番搜索,我想出了这个..它解决了我的“问题”,但不是我问的问题:-(
REPLACE INTO entity (entity_id,group_id,first_seen,last_seen)
SELECT r.entity_id AS entity_id
, r.group_id AS group_id
, ISNULL( e.first_seen
,r.record_date
) AS first_seen
, r.record_date AS last_seen
FROM entity_raw r
LEFT OUTER JOIN entity e ON ( r.entity_id=e.entity_id
AND r.group_id=e.group_id
)
WHERE (record_date = DATE(DATE_SUB(NOW(),INTERVAL 1 DAY))
The initial insert needs to be done with the where clause disabled (there were already 5weeks of data in the entity_raw table)
初始插入需要在禁用where子句的情况下完成(entity_raw表中已有5周的数据)
#1
2
No, what you're asking isn't possible without triggers. The only example in MySQL where a field can be assigned a default value from a function is the TIMESTAMP type that can have CURRENT_TIMESTAMP as default.
不,没有触发器,你所要求的是不可能的。 MySQL中唯一可以为函数分配默认值的示例是TIMESTAMP类型,它可以将CURRENT_TIMESTAMP作为默认值。
#2
1
To be honest it's pretty much impossible to combine an update or insert into one statement.
说实话,将更新或插入组合成一个语句几乎是不可能的。
If you are using a script, I would do as you suggested. First check for existence, then update or insert accordingly.
如果您使用的是脚本,我会按照您的建议进行操作。首先检查是否存在,然后相应地更新或插入。
Otherwise a trigger or stored procedure would do the job.
否则,触发器或存储过程将完成这项工作。
#3
1
You could use the TIMESTAMP
data type, which allows a default value of CURRENT_TIMESTAMP
, but that would set it to NOW()
and not to a day ago.
您可以使用TIMESTAMP数据类型,它允许默认值CURRENT_TIMESTAMP,但这会将其设置为NOW()而不是前一天。
So, I would rather use use an INSERT... ON DUPLICATE KEY UPDATE
statement:
所以,我宁愿使用INSERT ... ON DUPLICATE KEY UPDATE语句:
INSERT INTO entity (entity_id,group_id,first_seen,last_seen)
SELECT entity_id,group_id,record_date, record_date
FROM entity_raw
WHERE (record_date = DATE(DATE_SUB(NOW(),INTERVAL 1 DAY))
ON DUPLICATE KEY UPDATE last_seen = VALUES(last_seen)
with a unique index en entity_id
and/or group_id
. This will overwrite only last_seen
when an existing row is found.
具有唯一索引en entity_id和/或group_id。当找到现有行时,这将仅覆盖last_seen。
#4
0
After some searching I came up with this .. it solves my "problem", but not the question I asked :-(
经过一番搜索,我想出了这个..它解决了我的“问题”,但不是我问的问题:-(
REPLACE INTO entity (entity_id,group_id,first_seen,last_seen)
SELECT r.entity_id AS entity_id
, r.group_id AS group_id
, ISNULL( e.first_seen
,r.record_date
) AS first_seen
, r.record_date AS last_seen
FROM entity_raw r
LEFT OUTER JOIN entity e ON ( r.entity_id=e.entity_id
AND r.group_id=e.group_id
)
WHERE (record_date = DATE(DATE_SUB(NOW(),INTERVAL 1 DAY))
The initial insert needs to be done with the where clause disabled (there were already 5weeks of data in the entity_raw table)
初始插入需要在禁用where子句的情况下完成(entity_raw表中已有5周的数据)