Sql server 在同一个表上插入和更新的触发器

Sql server 在同一个表上插入和更新的触发器,sql-server,triggers,Sql Server,Triggers,众所周知,实体框架不能保存地理数据。所以我的想法是,在我的模型中将经度和纬度指定为十进制。在执行用于创建表的SQL脚本之后,我将启动另一个用于添加地理列的脚本。然后我想通过触发器在每次插入或更新经度和纬度时更新此列。下面的触发器是正常的,还是坏的?我问这个问题是因为我对触发器不太熟悉,但它现在可以用了 CREATE TRIGGER Update_Geography ON [People] FOR INSERT, UPDATE AS BEGIN DECLARE @longitude D

众所周知,实体框架不能保存地理数据。所以我的想法是,在我的模型中将经度和纬度指定为十进制。在执行用于创建表的SQL脚本之后,我将启动另一个用于添加地理列的脚本。然后我想通过触发器在每次插入或更新经度和纬度时更新此列。下面的触发器是正常的,还是坏的?我问这个问题是因为我对触发器不太熟悉,但它现在可以用了


CREATE TRIGGER Update_Geography 
ON [People]
FOR INSERT, UPDATE
AS
BEGIN
    DECLARE @longitude DECIMAL(8, 5), @latitude DECIMAL(8, 5)

    SET @longitude = (SELECT ins.Location_Longitude FROM inserted ins)
    SET @latitude = (SELECT ins.Location_Latitude FROM inserted ins)

    IF (@longitude != 0 AND @latitude != 0)
    BEGIN
        UPDATE [People]
        SET
            Location_Geography = geography::STGeomFromText('POINT(' + CONVERT(VARCHAR(100),@longitude) + ' ' +  CONVERT(VARCHAR(100),@latitude) + ')',4326)
        WHERE
            Id = (SELECT ins.Id FROM inserted ins)
    END
END
如果有人能帮助我,我会很高兴的

问候

编辑:

脚本如下所示:


ALTER TABLE [People] ADD Location_Geography AS (
    CONVERT(GEOGRAPHY, CASE
        WHEN Location_Latitude  0 AND Location_Longitude  0 THEN
            geography::STGeomFromText('POINT(' + CONVERT(VARCHAR, Location_Longitude) + ' ' + CONVERT(VARCHAR, Location_Latitude) + ')',4326)
        ELSE
            NULL
    END
    )
)
工作,但无法查询该列:/
Thx

尝试持久化计算列:此处可能需要外部强制转换

Location_Geography AS (
    CASE
        WHEN Location_Latitude <> 0 AND Location_Longitude <> 0 THEN
            geography::STGeomFromText('POINT(' + CONVERT(VARCHAR(100),Location_Longitude) + ' ' +  CONVERT(VARCHAR(100),Location_Latitude) + ')',4326)
        ELSE
        NULL
    END
)
下面是一个显示手动和计算列的示例:

IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'[dbo].[SO5572806]')
                    AND type IN (N'U') ) 
    DROP TABLE [dbo].[SO5572806]
GO

CREATE TABLE SO5572806
    (
     lo DECIMAL(8, 5) NOT NULL
    ,la DECIMAL(8, 5) NOT NULL
    ,man GEOGRAPHY NULL
    ,calc AS (CONVERT(GEOGRAPHY, CASE WHEN la <> 0
                                        AND lo <> 0
                                   THEN GEOGRAPHY::STGeomFromText('POINT('
                                                              + CONVERT(VARCHAR, lo)
                                                              + ' '
                                                              + CONVERT(VARCHAR, la)
                                                              + ')', 4326)
                                   ELSE NULL
                              END))
    )
GO

INSERT  INTO dbo.SO5572806
        (lo, la)
VALUES  (0, 0),
        (-90, 30)

UPDATE  dbo.SO5572806
SET     man = GEOGRAPHY::STGeomFromText('POINT(' + CONVERT(VARCHAR, lo) + ' '
                                      + CONVERT(VARCHAR, la) + ')', 4326)
WHERE   lo <> 0
        AND la <> 0

SELECT  *
FROM    dbo.SO5572806

如果任何进程更新或插入一批记录,触发器将导致数据完整性问题。永远不要在只插入一条记录的情况下编写触发器。请投票选择此连接项:但如果经度和纬度发生变化怎么办?@john任何一行更新时,都会重新计算一个持久化的计算列,就像触发器一样-请查看Books Online链接。触发器可以更智能,不需要通过检查某些列是否更改来计算内容,但触发器还必须确保它在整个插入的伪表上运行,而不是只假设一行。您可能需要检查的唯一一件事是几何体函数是确定性的。例如,除非指定了固定格式,否则将VARCHAR转换为DATETIME是不确定的。@john,我也在这里为您发布了其他触发器代码。@cade,很抱歉,如果我试图在visual studio中显示表内容,我会出错。我将用我所做的更新我的第一篇文章。@john我的测试显示该列的手动版本与calc版本相同-我不确定您看到了什么。我将把这个代码添加到我的答案中
IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'[dbo].[SO5572806]')
                    AND type IN (N'U') ) 
    DROP TABLE [dbo].[SO5572806]
GO

CREATE TABLE SO5572806
    (
     lo DECIMAL(8, 5) NOT NULL
    ,la DECIMAL(8, 5) NOT NULL
    ,man GEOGRAPHY NULL
    ,calc AS (CONVERT(GEOGRAPHY, CASE WHEN la <> 0
                                        AND lo <> 0
                                   THEN GEOGRAPHY::STGeomFromText('POINT('
                                                              + CONVERT(VARCHAR, lo)
                                                              + ' '
                                                              + CONVERT(VARCHAR, la)
                                                              + ')', 4326)
                                   ELSE NULL
                              END))
    )
GO

INSERT  INTO dbo.SO5572806
        (lo, la)
VALUES  (0, 0),
        (-90, 30)

UPDATE  dbo.SO5572806
SET     man = GEOGRAPHY::STGeomFromText('POINT(' + CONVERT(VARCHAR, lo) + ' '
                                      + CONVERT(VARCHAR, la) + ')', 4326)
WHERE   lo <> 0
        AND la <> 0

SELECT  *
FROM    dbo.SO5572806