【问题标题】:converting a mySQL Trigger, to TSQL将 mySQL 触发器转换为 SQL
【发布时间】:2018-03-28 17:23:20
【问题描述】:

寻求帮助将此 mySQL 触发器转换为 TSQL。

CREATE TRIGGER IF not exists TF_WATCHLIST_PERSISTENCE_ADD_POSITION 
AFTER INSERT ON TF_WATCHLIST_PERSISTENCE
FOR EACH ROW
WHEN NEW.WATCHLIST_POSITION IS NULL
BEGIN 
    UPDATE TF_WATCHLIST_PERSISTENCE SET
    WATCHLIST_POSITION = (SELECT COUNT(*) - 1 FROM TF_WATCHLIST_PERSISTENCE WHERE WATCHLIST_USER = NEW.WATCHLIST_USER)
    WHERE rowid = NEW.rowid;
END;

【问题讨论】:

  • 试试这个:CREATE TRIGGER TF_WATCHLIST_PERSISTENCE_ADD_POSITION AFTER INSERT ON TF_WATCHLIST_PERSISTENCE BEGIN UPDATE TF_WATCHLIST_PERSISTENCE SET WATCHLIST_POSITION = (SELECT COUNT(*) - 1 FROM TF_WATCHLIST_PERSISTENCE WHERE WATCHLIST_USER = inserted.WATCHLIST_USER) WHERE rowid = inserted.rowid and inserted.WATCHLIST_POSITION is null
  • 谢谢...但是我的 Management Studio 不接受该语法。如果我更好地重写它.WATCHLIST_POSITION 为 null 但是它需要一个“AS,NOT_FOR,With”
  • 你在使用 ssms 吗?
  • 我正在使用 Microsoft SQL Server Management Studio (2014)
  • @SimonBruun 这个触发器应该做什么?可能有一个 function 已经这样做了,而不需要触发器。 MySQL 没有窗口、分析或排名函数。 SQL Server 有一个 lot - ROW_NUMBER(), RANK(), LAG(),LEAD(),可以应用于所有数据或部分数据。看起来你只需要一个排名功能?

标签: mysql sql-server tsql


【解决方案1】:

感谢大家的帮助

我最终得到了这个。

CREATE TRIGGER TF_WATCHLIST_PERSISTENCE_ADD_POSITION 
ON TF_WATCHLIST_PERSISTENCE
AFTER INSERT, UPDATE
AS
DECLARE @MyCursor CURSOR;
DECLARE @MyField_USER varchar(250);
DECLARE @MyField_ID varchar(250);
DECLARE @MyField_NewPos int

BEGIN 
SET @MyCursor = CURSOR FOR 
SELECT      WATCHLIST_USER
        ,   WATCHLIST_ID
FROM    inserted
WHERE inserted.WATCHLIST_POSITION is null

OPEN @MyCursor 
FETCH NEXT FROM @MyCursor
INTO @MyField_USER,  @MyField_ID

WHILE @@FETCH_STATUS = 0

BEGIN 
    set @MyField_NewPos = (SELECT MAX(WATCHLIST_POSITION) + 1 FROM TF_WATCHLIST_PERSISTENCE WHERE WATCHLIST_USER = @MyField_USER)
    print @MyField_NewPos

    update TF_WATCHLIST_PERSISTENCE 
        SET WATCHLIST_POSITION = ISNULL(@MyField_NewPos,0)
        WHERE       WATCHLIST_USER = @MyField_USER 
            AND     WATCHLIST_ID = @MyField_ID
            AND     WATCHLIST_POSITION IS NULL 

        Print @MyField_USER 
        Print @MyField_ID
        FETCH NEXT FROM @MyCursor
        INTO @MyField_USER,  @MyField_ID
END;


END;
CLOSE @MyCursor

【讨论】:

  • 为什么?您不需要 cursor 来计算每个用户的递增值。这将比等效的单次更新慢 N 倍,其中 N 是行数。为什么不使用ROW_POSITION()?如果你想从以前的最大值开始,也可以添加MAX()
【解决方案2】:

我怀疑您正在寻找排名功能,甚至是每个用户的简单COUNT(*)? MySQL 在analyticranking 或窗口函数方面相当差,因此使用古怪的更新或触发器等技巧来模拟它们。

在 SQL Server 中,您可以返回与每行中单个用户匹配的记录数,并将COUNT() 应用于匹配单个用户的记录:

SELECT *, COUNT(*) OVER (PARTITION BY WATCHLIST_USER)
FROM TF_WATCHLIST_PERSISTENCE 

不需要触发器。您可以使用任何带有 OVER() 子句的聚合。

如果您希望按照某种顺序排名,您可以使用ROW_NUMBER() 或`RANK() 等排名函数之一。如果你想计算每个用户的行位置,例如在创建日期,你可以写:

SELECT *, ROW_NUMBER(*) OVER (PARTITION BY WATCHLIST_USER ORDER BY CreationDate)
FROM TF_WATCHLIST_PERSISTENCE 

如果您有一个递增的 ID,您可以使用它为每个用户生成一个 row position

SELECT *, ROW_NUMBER(*) OVER (PARTITION BY WATCHLIST_USER ORDER BY ID)
FROM TF_WATCHLIST_PERSISTENCE 

大多数时候,您不需要存储行位置。向查询添加排名函数很简单。

如果您确实需要在表格中存储这样的行位置,您可以使用简单的多行触发器

CREATE TRIGGER TF_WATCHLIST_PERSISTENCE_ADD_POSITION 
ON TF_WATCHLIST_PERSISTENCE
AFTER INSERT, UPDATE
AS
    update TF_WATCHLIST_PERSISTENCE 
    set WATCHLIST_POSITION =ROW_NUMBER() OVER (PARTITION BY WATCHLIST_USER ORDER BY ID)
    FROM inserted 
    INNER JOIN TF_WATCHLIST_PERSISTENCE on inserted.ID=TF_WATCHLIST_PERSISTENCE.ID

或者

update TF_WATCHLIST_PERSISTENCE 
set WATCHLIST_POSITION =ROW_NUMBER() OVER (PARTITION BY WATCHLIST_USER ORDER BY ID)
FROM inserted 
INNER JOIN TF_WATCHLIST_PERSISTENCE 
    ON inserted.WATCHLIST_USER =TF_WATCHLIST_PERSISTENCE.WATCHLIST_USER 

如果您想为现有用户插入新条目并重新计算所有位置

【讨论】:

    【解决方案3】:

    试试这个:

    CREATE TRIGGER TF_WATCHLIST_PERSISTENCE_ADD_POSITION ON TF_WATCHLIST_PERSISTENCE  AFTER INSERT 
    AS
    BEGIN 
        WITH DataSource AS
        (
            SELECT DS.WATCHLIST_USER
                  ,COUNT(*) - 1 AS WATCHLIST_POSITION
            FROM TF_WATCHLIST_PERSISTENCE DS
            INNER JOIN inserted I
                ON DS.WATCHLIST_USER = I.WATCHLIST_USER
            WHERE inserted.WATCHLIST_POSITION is null
            GROUP BY DS.WATCHLIST_USER
        )
        UPDATE TF_WATCHLIST_PERSISTENCE
        SET WATCHLIST_POSITION = DS.[WATCHLIST_POSITION]
        FROM TF_WATCHLIST_PERSISTENCE DS
        INNER JOIN DataSource I
            ON DS.WATCHLIST_USER = I.WATCHLIST_USER;
    END
    

    【讨论】:

    • 嗨 gotqn 我收到以下错误:消息 207,级别 16,状态 1,过程 TF_WATCHLIST_PERSISTENCE_ADD_POSITION,第 6 行无效的列名称“rowid”。消息 4104,级别 16,状态 1,过程 TF_WATCHLIST_PERSISTENCE_ADD_POSITION,第 6 行 无法绑定多部分标识符“inserted.rowid”。消息 4104,级别 16,状态 1,过程 TF_WATCHLIST_PERSISTENCE_ADD_POSITION,第 6 行无法绑定多部分标识符“inserted.WATCHLIST_POSITION”。
    • @SimonBruun 你能再试一次吗?
    • rowid 不是 TF_WATCHLIST_PERSISTENCE 表中的永久列。我认为 rowid 是 mySQL 中的内置“列”。 TF_WATCHLIST_PERSISTENCE 定义:CREATE TABLE [dbo].[TF_WATCHLIST_PERSISTENCE]( [WATCHLIST_USER] [varchar](250) NOT NULL, [WATCHLIST_ID] [varchar](250) NOT NULL, [WATCHLIST_DATA] [varchar](4000) NOT NULL, [ WATCHLIST_POSITION] [int] NULL,主键集群([WATCHLIST_USER] ASC,[WATCHLIST_ID] ASC)
    • @SimonBruun 你有 ID/ 主键列,我们可以在其上执行连接吗?
    • 不,不是 atm :( .. 我认为您的第一个建议让我们朝着一个好的方向前进:在插入开始更新 TF_WATCHLIST_PERSISTENCE 后在 TF_WATCHLIST_PERSISTENCE 上创建触发器 TF_WATCHLIST_PERSISTENCE_ADD_POSITION TF_WATCHLIST_PERSISTENCE SET WATCHLIST_POSITION = (SELECT COUNT(* ) - 1 FROM TF_WATCHLIST_PERSISTENCE WHERE WATCHLIST_USER = inserted.WATCHLIST_USER) WHERE rowid = Inserted.rowid 和 Inserted.WATCHLIST_POSITION 为空 END
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    • 2013-07-16
    • 2011-09-11
    相关资源
    最近更新 更多