Изменение хранимой процедуры — Cursor MSSQL

#sql #sql-server #tsql #stored-procedures

#sql #sql-сервер #tsql #хранимые процедуры

Вопрос:

Я хотел знать, возможно ли это сделать на SQL Server, чтобы сделать это другим способом, чем курсоры, потому что это очень медленно. Установите курсор, который проверяет строку перед самим собой, и ЕСЛИ @Machine <> @MachineCur ИЛИ @MachineStatus <> @MachinestatusCur ИЛИ @sShift <> @sShiftCur затем выполните вставку в таблицу.

код:

     SET ANSI_NULLS ON

    GO SET QUOTED_IDENTIFIER ON GO

    CREATE PROCEDURE [DBO].[MSTATE] @STARTDATE AS DATE, @ENDDATE AS DATE AS

    BEGIN

    SET NOCOUNT ON

    DECLARE @LINE AS VARCHAR(255), @MACHINE AS VARCHAR(255), @OBJECTTYPE AS VARCHAR(15), @INV AS VARCHAR(9), @MACHINESTATUS AS VARCHAR(255), @TIMESTART AS DATETIME, @TIMEEND AS DATETIME, @SSHIFT AS VARCHAR(100), @LINECUR AS VARCHAR(255), @MACHINECUR AS VARCHAR(255), @OBJECTTYPECUR AS VARCHAR(15), @INVCUR AS VARCHAR(9), @MACHINESTATUSCUR AS VARCHAR(255), @TIMESTARTCUR AS DATETIME, @TIMEENDCUR AS DATETIME, @SSHIFTCUR AS VARCHAR(100), @FIRST AS BIT

    IF @STARTDATE IS NULL SET @STARTDATE = '2015-01-01'
    IF @ENDDATE IS NULL SET @ENDDATE = GETDATE()

    TRUNCATE TABLE [DBO].[MSTATETEMP]

    DECLARE CUR10 CURSOR FOR

    SELECT [LINE],[MACHINE],[OBJECTTYPE],[INV],[MACHINESTATUS],[TIMESTART],[TIMEEND],[SSHIFT] FROM [DBO].[OEEQSTATEDATAPREVIEW] WHERE TIMESTART >= @STARTDATE AND TIMEEND <= @ENDDATE ORDER BY MACHINE, TIMESTART


    SET @FIRST = 0

        OPEN CUR10
                FETCH NEXT FROM CUR10 INTO @LINE, @MACHINE, @OBJECTTYPE, @INV, @MACHINESTATUS, @TIMESTART, @TIMEEND, @SSHIFT
            WHILE (@@FETCH_STATUS = 0)
        BEGIN

            IF @FIRST = 0   BEGIN

                                SET @LINECUR = @LINE
                                SET @MACHINECUR = @MACHINE
                                SET @OBJECTTYPECUR = @OBJECTTYPE 
                                SET @INVCUR = @INV
                                SET @MACHINESTATUSCUR = @MACHINESTATUS
                                SET @TIMESTARTCUR = @TIMESTART
                                SET @TIMEENDCUR = @TIMEEND 
                                SET @SSHIFTCUR = @SSHIFT
                                SET @FIRST = 1
                            END     

            IF @MACHINE <> @MACHINECUR OR @MACHINESTATUS <> @MACHINESTATUSCUR OR @SSHIFT <> @SSHIFTCUR
                        BEGIN   
                                INSERT INTO [DBO].[MSTATETEMP] (LINE, MACHINE, OBJECTTYPE, INV, MACHINESTATUS, TIMESTART, TIMEEND, SSHIFT) 
                                VALUES(@LINECUR, @MACHINECUR, @OBJECTTYPECUR, @INVCUR, @MACHINESTATUSCUR, @TIMESTARTCUR, @TIMESTART, @SSHIFTCUR)
                                SET @LINECUR = @LINE
                                SET @MACHINECUR = @MACHINE
                                SET @OBJECTTYPECUR = @OBJECTTYPE 
                                SET @INVCUR = @INV
                                SET @MACHINESTATUSCUR = @MACHINESTATUS
                                SET @TIMESTARTCUR = @TIMESTART
                                SET @TIMEENDCUR = @TIMEEND 
                                SET @SSHIFTCUR = @SSHIFT
                        END
            FETCH NEXT FROM CUR10 INTO @LINE, @MACHINE, @OBJECTTYPE, @INV, @MACHINESTATUS, @TIMESTART, @TIMEEND, @SSHIFT
        END
        CLOSE CUR10
        DEALLOCATE CUR10

        SELECT LINE, MACHINE, OBJECTTYPE, INV, MACHINESTATUS, TIMESTART, TIMEEND, SSHIFT FROM [DBO].[MSTATETEMP] ORDER BY MACHINE, TIMESTART

    END
 

Результат [DBO].[OEEQSTATEDATAPREVIEW] (Вставленная строка будет 1 и 3):

 Line    Machine OBJECTTYPE  INV         MACHINESTATUS   TIMESTART               TIMEEND                 SSHIFT
410     410     Linje       Invald      limit kapacitet 2015-11-06 17:00:00.000 2015-11-06 17:10:00.000 Night
410     410     Linje       Invald      limit kapacitet 2015-11-06 17:20:00.000 2015-11-06 17:30:00.000 Night
410     410     Linje       Ej invald   Avstalld        2015-11-06 19:21:01.000 2015-11-06 19:21:04.000 Night
 

Комментарии:

1. Похоже, вы можете просто вставить на основе вашего выбора, присоединившись к представлению и таблице

2. Избегайте механизмов зацикливания. Здесь вы можете написать просто запрос select с условием where, который вы упомянули в инструкции IF, и вставить его.

3. Дело в том, что каждая строка в исходном коде должна проверять свою строку выше, если критерии IF соответствуют или нет (если нет, то вставьте). Нужна помощь, как мне справиться с этим senario без курсора.

4. Не могли бы вы показать мне [DBO].[OEEQSTATEDATAPREVIEW] столбцы? Похоже, вам не обязательно иметь повторяющиеся значения для определенных столбцов — вставляйте только уникальные комбинации.

5. OEEQSTATEDATAPREVIEW — это представление, результат помещен в раздел кода.

Ответ №1:

Попробуйте использовать CTE для создания уникальных идентификаторов строк, затем вы можете выполнить простой выбор

 WITH CTE AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY Machine,TimeStart,TimeEnd) AS RowNum
        ,*
    FROM DBO.OEEQSTATEDATAPREVIEW
)
INSERT INTO MSTATETEMP
(Line,Machine,OBJECTTYPE,INV,MACHINESTATUS,TIMESTART,TIMEEND,SSHIFT)
SELECT Line,Machine,OBJECTTYPE,INV,MACHINESTATUS,TIMESTART,TIMEEND,SSHIFT
FROM CTE AS C
WHERE C.RowNum = 1
    OR EXISTS
    (
        SELECT 1 
        FROM CTE AS _C
        WHERE C.RowNum = _C.RowNum   1
            AND (C.Machine <> _C.Machine OR C.MACHINESTATUS <> _C.MACHINESTATUS OR C.SSHIFT <> _C.SSHIFT)
    )
    ;
 

Комментарии:

1. сначала я не силен в CTE, попробовал тот, который указан выше, но через 7 часов и без вставленной строки я остановил его. я сделал что-то не так или это так медленно?