скалярные функции sql

#sql-server #user-defined-functions

#sql-сервер #определяемые пользователем-функции

Вопрос:

В моем коде есть скалярная функция, которая вызывает другую скалярную функцию, которая вызывает 2 другие таблицы, как описано ниже. Я знаю, что это, должно быть, работает как свинья. Используется во всей базе данных… Моя проблема заключается в том, что немного не хватает навыков для разработки, чтобы переписать это как табличную функцию.

Я пытаюсь убедить некоторых разработчиков переписать функцию, но у нас есть только ребята из JAVA и нет специального разработчика SQL, поэтому они не видят никаких проблем. кто-нибудь может подсказать, как это следует переписать? большое спасибо…

 CREATE FUNCTION [dbo].[getInvertCurrencyExchangeRateByDate](@casino_id char(16),@currency_code char(3), @end_date datetime)
RETURNS float AS
BEGIN

declare @retval float;

set @retval = 
dbo.getCurrencyExchangeRateByDate(@casino_id,@currency_code,@end_date);

if (@retval != 0) return 1/@retval;
return 0;
END
  

 CREATE FUNCTION [dbo].[getCurrencyExchangeRateByDate](@casino_id char(16),@currency_code char(3), @end_date datetime)
RETURNS float AS
BEGIN

declare @retval float;
declare @casino_curr_code char(3);

set @casino_curr_code = 
(SELECT TOP 1 currency_code
FROM Casino
WHERE
casino_id=@casino_id 
);

if (@currency_code = @casino_curr_code) return 1;

set @retval = 
COALESCE(
(
SELECT TOP 1 exchange_rate
FROM CurrencyExchangeRateHistory
WHERE 
casino_id=@casino_id and 
currency_code=@currency_code AND 
transact_time <= @end_date
ORDER BY 
transact_time DESC
),0.0);

return @retval
END
  

Ответ №1:

Извините, но это чертовски много кода для чего-то довольно простого, я думаю, это удовлетворяет потребностям запроса.

 CREATE FUNCTION dbo.TVF(@casino_id char(16),@currency_code char(3), @end_date datetime)
RETURNS TABLE
AS
RETURN                          --IF THE JOIN FAILS OR RETURNS 0, DIVISION WILL NEVER HAPPEN AND FALL IN THE ISNULL
    SELECT TOP 1 CASE WHEN A.currency_code = @currency_code THEN 1 ELSE ISNULL(1/NULLIF(B.exchange_rate,0), 0) END AS RETVAL
    FROM Casino A
    LEFT JOIN CurrencyExchangeRateHistory B ON A.casino_id = B.casino_id AND B.transact_time <= @end_date AND B.currency_code = A.currency_code
    WHERE A.casino_id = @casino_id
    ORDER BY B.transact_time DESC