Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Не могу вызвать пользовательскую функцию  [new]
fenix_63
Member

Откуда: Тольятти
Сообщений: 47
Всем привет. Народ, написал я вот такую функцию - она возвращает количество дней месяца даты, переданной ей в качестве параметра:


Create Function DayCount(@curdate varchar)
returns int
AS
begin
	declare @dayCount int
	set @dayCount = day(dateadd(dd, -day(dateadd(mm, 1, @curdate)), dateadd(mm, 1, @curdate)))
	return @dayCount
end


Вот сам вызов:
declare @date datetime = getdate()--текущая дата
Select DayCount(@date)


Ничего понять не могу, где я ошибся? Помогите пожалуйста. Сама БД называется test. В раскрывающемся списке в SQL-Server 2015 выбрана она. Появилась в разделе Программирование -> Функции -> Скалярные функции.

Помогите пожалуйста.
13 апр 17, 20:40    [20400467]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
fenix_63,

почему параметр типа varchar, а не datetime?
varchar - это строка длиной 1 символ, в курсе?
Функция вообще ни к чему:
SELECT
 CASE MONTH(@D)
  WHEN 1,3,5,7,8,10,12 THEN 31
  WHEN 4,6,9,11 THEN 30
  WHEN 2 THEN 28+ISDATE(STR(YEAR(@D))+'0229')
 END;

Для MSSQL2016:
SELECT DAY(EOMONTH(@D));
13 апр 17, 21:00    [20400513]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
o-o
Guest
declare @date datetime = getdate()--текущая дата
Select dbo.DayCount(@date)
13 апр 17, 21:17    [20400552]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
fenix_63
Member

Откуда: Тольятти
Сообщений: 47
Ругается компилятор, я вот так сделал по твоему примеру:

Declare @D datetime
Set @D = getdate()

 SELECT
 CASE MONTH(@D)
  WHEN @D IN (1,3,5,7,8,10,12) THEN 31
  WHEN @D IN (4,6,9,11) THEN 30
  WHEN 2 THEN 28+ISDATE(STR(YEAR(@D))+'0229')
 END;


Но всё равно ругается
13 апр 17, 21:27    [20400578]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
iljy
Member

Откуда:
Сообщений: 8711
fenix_63,

Create Function dbo.DayCount(@curdate date)
returns int
AS
begin
	return DAY(DATEADD(dd, -1, DATEADD(mm, datediff(mm, 0, @curdate) + 1, 0)))
end
go

Select dbo.DayCount(d)
from (values ('20170417'), ('20160213'), ('20160131'), ('20170202')) t(d)

go 
drop function dbo.DayCount
14 апр 17, 00:40    [20400884]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
o-o
Guest
все это прекрасно,
но вопрос-то у него был, почему "Не могу вызвать пользовательскую функцию"
т.е. он ф-цию "видит":
автор
В раскрывающемся списке в SQL-Server 2015 выбрана она. Появилась в разделе Программирование -> Функции -> Скалярные функции.

а вызвать не может:
Msg 195, Level 15, State 10, Line 2
'DayCount' is not a recognized built-in function name.

и это потому, что схему надо писать.
потому что без схемы он ищет built-in, а не user defined function
14 апр 17, 00:51    [20400902]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
fenix_63
Member

Откуда: Тольятти
Сообщений: 47
В общем функцию я немного поменял:


Create Function DayCount(@curdate datetime)
returns int
AS
begin
	declare @dayCount int
	set @dayCount = day(dateadd(dd, -day(dateadd(mm, 1, @curdate)), dateadd(mm, 1, @curdate)))
	return @dayCount
end


Вызов теперь вот такой (точнее вызовы):

declare @date datetime = getdate()--текущая дата
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)

set @date = DATEADD(month,1,@date)
Select dbo.DayCount(@date)


Да, действительно забыл схему указать.

Вариант, который предложил iap тоже хорош.

Вопрос у меня теперь такой. Сейчас тут у меня 12 вызовов этой функции. Т.е. Я к текущей дате просто прибавляю 1 месяц, и новую дату передаю в функцию как аргумент, функция уже считает кол-во дней в новом месяце.

Как бы сделать так, чтоб выводилось не 12 запросов, а 1 запрос вот такого вида? :

Месяц Кол-во дней

4 30
5 31
6 30
7 31
8 31
9 30
10 31
11 30
12 31
1 31
2 28
3 31


По сути тут только в феврале кол-во дней меняется, но тем не менее.
14 апр 17, 08:43    [20401104]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
IDVT
Member

Откуда:
Сообщений: 320
Вам нужно использовать в одном запросе таблицу календарь (уникальные значения по полю месяц или первый числа по полю дата) + Ваша функция с фильтрацией по нужному году.

Но лично я бы использовал вариант предложенный iap

SELECT DAY(EOMONTH(@D, 1)) -- где 1 (второй аргумент функции) и есть следующий месяц;
14 апр 17, 09:04    [20401162]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
aleks2
Guest
fenix_63
Как бы сделать так, чтоб выводилось не 12 запросов, а 1 запрос вот такого вида? :

Месяц Кол-во дней

4 30
5 31
6 30
7 31
8 31
9 30
10 31
11 30
12 31
1 31
2 28
3 31


По сути тут только в феврале кол-во дней меняется, но тем не менее.


Внезапно! Забабахать табличку-справочник и не мучить жЫвотное.
14 апр 17, 09:05    [20401169]     Ответить | Цитировать Сообщить модератору
 Re: Не могу вызвать пользовательскую функцию  [new]
o-o
Guest
declare @date datetime = getdate();--текущая дата

with cte as
(
select dateadd(month, n, a.first) as first_dd
from (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11)) v(n)
cross apply (select cast(stuff(convert(char(8), @date, 112), 7, 2, '01') as date) as first) a
)

select month(first_dd) as mm, datediff(day, first_dd, dateadd(month, 1, first_dd)) as nn
from cte;
14 апр 17, 09:41    [20401310]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить