У меня возникли проблемы с преобразованием этой функции MySQL в SQl Server или даже в код C# для структуры сущностей.
Я буду использовать этот код с базой данных GEO Lite, чтобы получить информацию о местоположении по IP-адресу.
BEGIN
DECLARE loc_id INT;
SELECT geoname_id
INTO loc_id
FROM ip_blocks
WHERE ip_to >= INET_ATON(TRIM(ip))
ORDER BY ip_to LIMIT 1;
RETURN IFNULL(loc_id, 0);
END
Я попытался создать эту функцию SQL Server, чтобы заменить функцию mysql INET_ATON
CREATE FUNCTION dbo.ipStringToInt (@ip CHAR(15))
RETURNS INT
AS
BEGIN
DECLARE @rv INT
,@o1 INT
,@o2 INT
,@o3 INT
,@o4 INT
,@base INT
SELECT @o1 = CONVERT(INT, PARSENAME(@ip, 4))
,@o2 = CONVERT(INT, PARSENAME(@ip, 3))
,@o3 = CONVERT(INT, PARSENAME(@ip, 2))
,@o4 = CONVERT(INT, PARSENAME(@ip, 1))
IF (
@o1 BETWEEN 0
AND 255
)
AND (
@o2 BETWEEN 0
AND 255
)
AND (
@o3 BETWEEN 0
AND 255
)
AND (
@o4 BETWEEN 0
AND 255
)
BEGIN
SELECT @base = CASE
WHEN @o1 < 128
THEN (@o1 * 16777216)
ELSE - (256 - @o1) * 16777216
END
SET @rv = @base + (@o2 * 65536) + (@o3 * 256) + (@o4)
END
ELSE
SET @rv = - 1
RETURN @rv
END
GO
А также преобразовать функцию MySQL в эту версию SQL Server:
CREATE FUNCTION IP2Location (@ip VARCHAR(50))
RETURNS INT
AS
BEGIN
DECLARE @loc_id INT
SET @loc_id = (
SELECT geoname_id
FROM ip_blocks
WHERE ip_to >= dbo.ipStringToInt(TRIM(@ip))
ORDER BY ip_to LIMIT 1
)
RETURN IFNULL(@loc_id, 0);
END
GO
Но я получаю такие ошибки, как Trim is not recognized built-in function name, что странно, потому что это так.
И на @loc_id появляется сообщение об ошибке, в котором говорится, что ожидается (.
Был бы признателен за помощь
Спасибо
РЕДАКТИРОВАТЬ №1: Моя функция теперь выглядит так:
CREATE FUNCTION IP2Location (@ip varchar(50)) RETURNS INTEGER
AS
BEGIN
DECLARE @loc_id INTEGER
SELECT top 1 geoname_id INTO @loc_id FROM ip_blocks WHERE ip_to >= dbo.ipStringToInt(LTRIM(RTRIM(@ip))) ORDER BY ip_to
RETURN isnull(@loc_id, 0);
END
go





В случае ошибки:
Trim is not recognized built-in function name
TRIM() доступен только начиная с SQL Server 2017.
Если вы не используете эту версию, используйте LTRIM(RTRIM(@ip)).
В случае ошибки:
And getting an error on @loc_id which says it is expecting (
Вместо IFNULL() я думаю, что вы ищете ISNULL()
В случае ошибки:
Invalid use of a side-effecting operator SELECT within a function
Вместо:
SET @loc_id = (
SELECT geoname_id
FROM ip_blocks
WHERE ip_to >= dbo.ipStringToInt(TRIM(@ip))
ORDER BY ip_to LIMIT 1
)
Или же:
SELECT TOP 1 geoname_id
INTO @loc_id
FROM ip_blocks
WHERE ip_to >= dbo.ipStringToInt(LTRIM(RTRIM(@ip)))
ORDER BY ip_to
Вместо этого используйте:
SET @loc_id = (
SELECT TOP 1 geoname_id
FROM ip_blocks
WHERE ip_to >= dbo.ipStringToInt(LTRIM(RTRIM(@ip)))
ORDER BY ip_to
)
Ошибка в этой функции: IP2Location?
Я обновил свой вопрос, чтобы показать последнюю версию, которая у меня есть после ваших исправлений, я получаю ошибку во всей строке SELECT
:) Я как раз собирался порекомендовать заменить использование LIMIT на TOP 1, но вы поняли. Хорошо, глядя на ваше редактирование
Это ваше использование SELECT INTO @loc_id. У вас все было правильно с первого раза, просто используйте SELECT TOP 1 geoname_id FROM.... Используйте SET, как вы это делали изначально
хахаха, это мой первый вопрос по SQL, поэтому я не знаю, кто такой Гордон, но вы бы его задницу надрали :)
Блин 650к, чувак конечно активный
Спасибо, чувак, у меня все еще есть
Invalid use of a side-effecting operator SELECT within a function, но другие ошибки исчезли