SQL Сервер - странное поведение с UDF и побитовыми операциями в предложении ORDER BY - PullRequest
0 голосов
/ 06 августа 2020

Я использую SQL Server 2014 SP3, и я наткнулся на очень странное поведение (или задокументированное поведение, которое я не смог найти) с предложением ORDER BY. Почему в следующем примере переменная count не всегда равна 5?

CREATE FUNCTION dbo.F_SmallintSignedToUnsigned (@Value SMALLINT)
RETURNS INT
AS  
BEGIN 
    RETURN CAST(@Value AS INT) & 0xFFFF;
END;
GO

CREATE TABLE dbo.TestTable
(
    id INT NOT NULL IDENTITY(1,1)
    , SmallintValue SMALLINT NOT NULL
);
GO

SET NOCOUNT ON;

INSERT INTO dbo.TestTable (SmallintValue) VALUES
(-100), (10), (3000), (-1), (-32768);

DECLARE @count INT;

PRINT 'Count variable should always be 5?';

SET @count = 0;
SELECT @count += 1 FROM dbo.TestTable TestT ORDER BY dbo.F_SmallintSignedToUnsigned(TestT.SmallintValue);
PRINT 'Count with UDF in ORDER BY: ' + CAST(@count AS VARCHAR(10));

SET @count = 0;
SELECT @count += 1 FROM dbo.TestTable TestT WHERE TestT.SmallintValue <> 999 ORDER BY dbo.F_SmallintSignedToUnsigned(TestT.SmallintValue);
PRINT 'Count with UDF in ORDER BY + WHERE clause: ' + CAST(@count AS VARCHAR(10));

SET @count = 0;
SELECT TOP(100) @count += 1 FROM dbo.TestTable TestT ORDER BY dbo.F_SmallintSignedToUnsigned(TestT.SmallintValue);
PRINT 'Count with UDF in ORDER BY + TOP(100): ' + CAST(@count AS VARCHAR(10));

SET @count = 0;
SELECT @count += 1 FROM dbo.TestTable TestT ORDER BY CAST(TestT.smallintvalue AS INT) & 0xFFFF;
PRINT 'Count with bitwise operation in ORDER BY: ' + CAST(@count AS VARCHAR(10));

SET @count = 0;
SELECT @count += 1 FROM dbo.TestTable TestT WHERE TestT.SmallintValue <> 999 ORDER BY CAST(TestT.smallintvalue AS INT) & 0xFFFF;
PRINT 'Count with bitwise operation in ORDER BY + WHERE clause: ' + CAST(@count AS VARCHAR(10));

SET @count = 0;
SELECT TOP(100) @count += 1 FROM dbo.TestTable TestT ORDER BY CAST(TestT.smallintvalue AS INT) & 0xFFFF;
PRINT 'Count with bitwise operation in ORDER BY + TOP(100): ' + CAST(@count AS VARCHAR(10));
...