Инструкция должна быть единственной в пакете sql

I’m getting this error from the function:

CREATE FUNCTION getLavel(@id int ,@lavel char)
RETURNS date
BEGIN
 DECLARE @date date
    select @date = (select authorization_date from Authorized WHERE diver_number = @id and @lavel =level_name)
    return @date
END
GO

What can be the reason?

Ty very much.

juergen d's user avatar

juergen d

201k36 gold badges290 silver badges357 bronze badges

asked Jul 28, 2014 at 19:31

user3885474's user avatar

3

The function needs to be either the only function in the query window OR the only statement in the batch. If there are more statements in the query window, you can make it the only one «in the batch» by surrounding it with GO’s.

e.g.

GO
CREATE FUNCTION getLavel(@id int ,@lavel char)
RETURNS date
BEGIN
 DECLARE @date date
    select @date = (select authorization_date from Authorized WHERE     diver_number = @id and @lavel =level_name)
    return @date
END
GO

answered May 28, 2015 at 8:54

nicV's user avatar

nicVnicV

6307 silver badges16 bronze badges

1

Turn this into an inline table valued function. This will perform better than the scalar function. Also, you should NOT use the default sizes for character datatypes. Do you know what the default length for a char is? Did you know that it can vary based on usage?

CREATE FUNCTION getLavel
(
    @id int
    , @lavel char --You need to define the length instead of the default length
) 
RETURNS table
return 
    select authorization_date 
    from Authorized 
    WHERE diver_number = @id 
        and @lavel = level_name

GO

answered Jul 28, 2014 at 19:38

Sean Lange's user avatar

Sean LangeSean Lange

32.9k3 gold badges24 silver badges39 bronze badges

5

You need to add RETURN before the END statement

That should fix your issue, that’s what fixed mine. :D

answered Sep 22, 2015 at 17:58

FoxArc's user avatar

FoxArcFoxArc

1149 bronze badges

Make sure that this statement is the only the only sql in your query window before you execute it.

Or you can highlight the function declaration and execute

Ben Thul's user avatar

Ben Thul

30.8k4 gold badges45 silver badges68 bronze badges

answered Jul 28, 2014 at 19:35

WantToBeAnonomous's user avatar

What solved it for me, was that I was trying to create the function inside of a transaction context — that doesn’t make sense from a SQL Server point of view. Transactions are for data, not functions.

Take the CREATE FUNCTION statement out of the transaction, then wrap it in GO’s

answered Dec 10, 2017 at 20:05

Michael Malone's user avatar

CREATE FUNCTION CalculateAge(@DOB  DATE) 
RETURNS INT 
AS
BEGIN
DECLARE @Age INT
SET @DOB='08/12/1990'
SET @Age =DATEDIFF(YEAR,@DOB,GETDATE()) -
   CASE
        WHEN (MONTH (@DOB)>  MONTH (GETDATE ())) OR
             (MONTH (@DOB)= MONTH (GETDATE ())  AND DAY (@DOB) >DAY (GETDATE ()))

    THEN 1 
    ELSE 0
    END 
SELECT @Age
END

Tunaki's user avatar

Tunaki

131k46 gold badges331 silver badges417 bronze badges

answered Jun 14, 2016 at 10:38

MR.Rabin Shrestha's user avatar

1

The Error is given to you in only query Page But if you execute the query then it will successfully execute.

CREATE FUNCTION getLavel(@id int ,@lavel char)
RETURNS date
BEGIN
 DECLARE @date date
    select @date = (select authorization_date from Authorized WHERE diver_number = @id and @lavel = level_name)
    return @date
END
GO

answered Oct 25, 2020 at 12:29

Adarsh Bhalani's user avatar

Вам необходимо убрать ключевое слово BEGIN перед началом создания функции, т.к. это вызывает синтаксическую ошибку: «CREATE FUNCTION» должна быть единственной в пакете

Для вызова каждого параметра по умолчанию, необходимо передать ключевое слово DEFAULT в верхнем регистре

Код должен выглядеть следующим образом

CREATE FUNCTION funkcja(@p1 int = 18, @p2 int = 30)
    RETURNS TABLE 
    AS
    RETURN (SELECT * FROM Employees 
            WHERE DATEDIFF(year, BirthDate, getdate()) between @p1 and @p2)
GO

BEGIN

    SELECT EmployeeID, LastName, FirstName, ROW_NUMBER(order by employyID desc) as number 
    FROM funkcja(DEFAULT, DEFAULT) 
    WHERE number  % 3 = 0
    order by desc

    GO
END;

#sql #sql-server #view #ssms

#sql #sql-сервер #Вид #ssms

Вопрос:

Microsoft SQL Server Management Studio 18 показывает ошибку:

CREATE VIEW должна быть единственной инструкцией в пакете

После выполнения запроса появляется следующая ошибка:

Неправильный синтаксис вокруг ключевого слова «select»

 create view revenue0 (supplier_no, total_revenue) as
    select
        l_suppkey,
        sum(l_extendedprice * (1 - l_discount))
    from
        lineitem
    where
        l_shipdate >= '1996-05-01'
        and l_shipdate < dateadd(mm,3,cast('1996-05-01' as datetime))
    group by
        l_suppkey;


select
s_suppkey,
s_name,
s_address,
s_phone,
total_revenue
from
supplier,
revenue0
where
    s_suppkey = supplier_no
    and total_revenue = (
        select
            max(total_revenue)
        from
            revenue0
    )
order by
s_suppkey
option (maxdop 2)
drop view revenue0
 

UPD. Я попытался запустить этот метод:

 create view revenue0 (supplier_no, total_revenue) as
    select
        l_suppkey,
        sum(l_extendedprice * (1 - l_discount))
    from
        lineitem
    where
        l_shipdate >= cast('1996-05-01' as datetime)
        and l_shipdate < dateadd(mm, 3, cast('1996-05-01' as datetime))
    group by
        l_suppkey;

go
select
    s_suppkey,
    s_name,
    s_address,
    s_phone,
    total_revenue
from
    supplier,
    revenue0
where
    s_suppkey = supplier_no
    and total_revenue = (
        select
            max(total_revenue)
        from
            revenue0
    )
order by
    s_suppkey;

drop view revenue0;
 

Но в результате выполнения запроса отображается ошибка:
Недопустимое имя объекта «revenue0».
Как только я не изменил свое имя. SQL все равно ругается на это имя.

UPD2. Вопрос был решен самостоятельно. Тема закрыта! Спасибо всем за ваши усилия!

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

1. Поместите слово GO после определения представления.

2. Можете ли вы сказать мне, где именно? Я не очень хорошо разбираюсь в SQL. Я буду очень благодарен!

3. group by l_suppkey; GO

4. Неправильный синтаксис вокруг конструкции «go».

5. вы не можете использовать «order by» в представлении, измените свой вид, чтобы не использовать его.

Ответ №1:

Ошибка сообщает, что CREATE VIEW должен быть единственным оператором в пакете. Пакет завершается в SQL Server ключевым словом «GO», как заявил Гордон, поэтому ваш код должен выглядеть следующим образом:

 create view revenue0 (supplier_no, total_revenue) as
    select
        l_suppkey,
        sum(l_extendedprice * (1 - l_discount))
    from
        lineitem
    where
        l_shipdate >= '1996-05-01'
        and l_shipdate < dateadd(mm,3,cast('1996-05-01' as datetime))
    group by
        l_suppkey;

GO -- right here. This ends a batch. Must be on a new line, with no semi-color, or SQL gets pissy. 

select
    s_suppkey,
    s_name,
    s_address,
    s_phone,
    total_revenue
from
    supplier,
    revenue0
where
    s_suppkey = supplier_no
    and total_revenue = (
        select
            max(total_revenue)
        from
            revenue0
    )
order by
    s_suppkey
option (maxdop 2); 

drop view revenue0;
 

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

1. Я тестирую «Тесты TPC-H на MS-SQL-Server» этот материал: ссылка . При выполнении этого запроса это должно быть: link .

2. Но у меня, с вашей поправкой, после выполнения SQL-запроса выводится пустая таблица. Время выполнения запроса составляет 0 секунд. Это ненормально.

3. Вы можете помочь переделать этот запрос, чтобы он работал: ссылка .

4. Я уже всю голову сломал с ним. Но этот конкретный запрос не хочет работать. Все остальные работают.

Вопрос:

Я пытаюсь сначала проверить, существует ли функция, и создать ее, если она не существует.

Я получаю эту ошибку от функции:

IF NOT EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[GetRelativeExpiry]') AND type in (N'U'))
BEGIN

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON

CREATE FUNCTION [dbo].[GetRelativeExpiry]
(
@Date DATE,
@N INT
)
RETURNS DATE
AS
BEGIN
-- Declare the return variable here
DECLARE @Expiry as DATE;

IF @N > 0
BEGIN
SELECT @Expiry = MAX(E2.Expiry)
FROM (SELECT TOP(@N) Expiry
FROM ExpiryDates E1
WHERE E1.Expiry >= @date
ORDER BY E1.Expiry) AS E2
END
ELSE
BEGIN
SELECT @Expiry = MIN(E2.Expiry)
FROM (SELECT TOP(-@N) Expiry
FROM ExpiryDates E1
WHERE E1.Expiry <= @date
ORDER BY E1.Expiry DESC) AS E2
END
RETURN @Expiry

END

END

Я не уверен, почему я получаю эту ошибку, может кто-то может помочь? Я использую Microsoft SQL Server Management Studio 2014

Лучший ответ:

Если вы пытаетесь сделать это в обычном окне в MS SQL Server Management Studio 2014 (или любой предыдущей версии), где вы обычно записываете все другие запросы, то ваше определение функции должно быть очень первым утверждением, которое не комментируется.

См. Изображение ниже. Если инструкция USE PTCRMstaging_test; не был прокомментирован, SQL Server Management Studio даст такую же ошибку.

enter image description here

Ответ №1

Операторы CREATE, будь то для TYPE, PROCEDURE, FUNCTION,... всегда должны быть первым оператором в пакете.

Чтобы обойти это в таких партиях, как ваш, выполните инструкцию CREATE с помощью sp_executesql следующим образом:

EXEC sp_executesql N'
-- your CREATE statement here
';

I’m getting this error from the function:

CREATE FUNCTION getLavel(@id int ,@lavel char)
RETURNS date
BEGIN
 DECLARE @date date
    select @date = (select authorization_date from Authorized WHERE diver_number = @id and @lavel =level_name)
    return @date
END
GO

What can be the reason?

Ty very much.

juergen d's user avatar

juergen d

201k36 gold badges290 silver badges355 bronze badges

asked Jul 28, 2014 at 19:31

user3885474's user avatar

3

The function needs to be either the only function in the query window OR the only statement in the batch. If there are more statements in the query window, you can make it the only one «in the batch» by surrounding it with GO’s.

e.g.

GO
CREATE FUNCTION getLavel(@id int ,@lavel char)
RETURNS date
BEGIN
 DECLARE @date date
    select @date = (select authorization_date from Authorized WHERE     diver_number = @id and @lavel =level_name)
    return @date
END
GO

answered May 28, 2015 at 8:54

nicV's user avatar

nicVnicV

6307 silver badges16 bronze badges

1

Turn this into an inline table valued function. This will perform better than the scalar function. Also, you should NOT use the default sizes for character datatypes. Do you know what the default length for a char is? Did you know that it can vary based on usage?

CREATE FUNCTION getLavel
(
    @id int
    , @lavel char --You need to define the length instead of the default length
) 
RETURNS table
return 
    select authorization_date 
    from Authorized 
    WHERE diver_number = @id 
        and @lavel = level_name

GO

answered Jul 28, 2014 at 19:38

Sean Lange's user avatar

Sean LangeSean Lange

32.8k3 gold badges26 silver badges39 bronze badges

5

You need to add RETURN before the END statement

That should fix your issue, that’s what fixed mine. :D

answered Sep 22, 2015 at 17:58

FoxArc's user avatar

FoxArcFoxArc

1149 bronze badges

Make sure that this statement is the only the only sql in your query window before you execute it.

Or you can highlight the function declaration and execute

Ben Thul's user avatar

Ben Thul

30.7k4 gold badges46 silver badges68 bronze badges

answered Jul 28, 2014 at 19:35

WantToBeAnonomous's user avatar

What solved it for me, was that I was trying to create the function inside of a transaction context — that doesn’t make sense from a SQL Server point of view. Transactions are for data, not functions.

Take the CREATE FUNCTION statement out of the transaction, then wrap it in GO’s

answered Dec 10, 2017 at 20:05

Michael Malone's user avatar

CREATE FUNCTION CalculateAge(@DOB  DATE) 
RETURNS INT 
AS
BEGIN
DECLARE @Age INT
SET @DOB='08/12/1990'
SET @Age =DATEDIFF(YEAR,@DOB,GETDATE()) -
   CASE
        WHEN (MONTH (@DOB)>  MONTH (GETDATE ())) OR
             (MONTH (@DOB)= MONTH (GETDATE ())  AND DAY (@DOB) >DAY (GETDATE ()))

    THEN 1 
    ELSE 0
    END 
SELECT @Age
END

Tunaki's user avatar

Tunaki

131k46 gold badges330 silver badges415 bronze badges

answered Jun 14, 2016 at 10:38

MR.Rabin Shrestha's user avatar

1

The Error is given to you in only query Page But if you execute the query then it will successfully execute.

CREATE FUNCTION getLavel(@id int ,@lavel char)
RETURNS date
BEGIN
 DECLARE @date date
    select @date = (select authorization_date from Authorized WHERE diver_number = @id and @lavel = level_name)
    return @date
END
GO

answered Oct 25, 2020 at 12:29

Adarsh Bhalani's user avatar

Всякий раз, когда я запускаю это вместе с другими инструкциями SQL, он выдает ошибку:

CREATE FUNCTION ‘должен быть первым оператором в пакете запроса

Однако всякий раз, когда я выполняю его один (без SELECT * FROM CUSTOMER в моем случае это работает)

   SELECT * FROM CUSTOMER;

   create function udfLogin
    (@username nvarchar(100), @password nvarchar(100)) 
    returns int as
    begin
      if exists(select 1 from CUSTOMER where Username = @username and [Password] = @password)
        return 1
      return 0;
    end

3 ответа

Лучший ответ

Вы должны отделить каждую партию кода с помощью ключевого слова GO.

SELECT * FROM CUSTOMER
 GO
   create function udfLogin
    (@username nvarchar(100), @password nvarchar(100)) 
     returns int as
     begin
      if exists(select 1 from CUSTOMER where Username = @username and 
      [Password] = @password)
       return 1
     return 0;
   end
Go


1

Mehrnoosh
27 Мар 2018 в 11:27

Как следует из сообщения об ошибке, оператор CREATE FUNCTION должен быть первым оператором в пакете запроса. Перед оператором CREATION FUNCTION не должно быть других операторов, которые сделали бы его не первым оператором в пакете запроса. Как следует из сообщения, чтобы избежать этой ошибки, оператор CREATE FUNCTION должен быть первым оператором в пакете запроса.

SQL выполняет инструкцию как пакет запроса.

Правила использования пакетов

Следующие правила применяются к использованию пакетов:

Операторы CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER и CREATE VIEW нельзя объединять с другими операторами в пакете. Оператор CREATE должен запустить пакет. Все остальные операторы, которые следуют в этом пакете, будут интерпретированы как часть определения первого оператора CREATE.


0

Karthik Venkatraman
27 Мар 2018 в 11:37

Вы должны включить разделитель партии, например, Go

SELECT * FROM CUSTOMER
GO
   create function udfLogin
    (@username nvarchar(100), @password nvarchar(100)) 
    returns int as
    begin
      if exists(select 1 from CUSTOMER where Username = @username and [Password] = @password)
        return 1
      return 0;
    end
Go


2

Mazhar
27 Мар 2018 в 11:26

Вопрос:

Я пытаюсь сначала проверить, существует ли функция, и создать ее, если она не существует.

Я получаю эту ошибку от функции:

IF NOT EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[GetRelativeExpiry]') AND type in (N'U'))
BEGIN

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON

CREATE FUNCTION [dbo].[GetRelativeExpiry]
(
@Date DATE,
@N INT
)
RETURNS DATE
AS
BEGIN
-- Declare the return variable here
DECLARE @Expiry as DATE;

IF @N > 0
BEGIN
SELECT @Expiry = MAX(E2.Expiry)
FROM (SELECT TOP(@N) Expiry
FROM ExpiryDates E1
WHERE E1.Expiry >= @date
ORDER BY E1.Expiry) AS E2
END
ELSE
BEGIN
SELECT @Expiry = MIN(E2.Expiry)
FROM (SELECT TOP(-@N) Expiry
FROM ExpiryDates E1
WHERE E1.Expiry <= @date
ORDER BY E1.Expiry DESC) AS E2
END
RETURN @Expiry

END

END

Я не уверен, почему я получаю эту ошибку, может кто-то может помочь? Я использую Microsoft SQL Server Management Studio 2014

Лучший ответ:

Если вы пытаетесь сделать это в обычном окне в MS SQL Server Management Studio 2014 (или любой предыдущей версии), где вы обычно записываете все другие запросы, то ваше определение функции должно быть очень первым утверждением, которое не комментируется.

См. Изображение ниже. Если инструкция USE PTCRMstaging_test; не был прокомментирован, SQL Server Management Studio даст такую же ошибку.

enter image description here

Ответ №1

Операторы CREATE, будь то для TYPE, PROCEDURE, FUNCTION,... всегда должны быть первым оператором в пакете.

Чтобы обойти это в таких партиях, как ваш, выполните инструкцию CREATE с помощью sp_executesql следующим образом:

EXEC sp_executesql N'
-- your CREATE statement here
';

#sql #sql-server #view #ssms

#sql #sql-сервер #Вид #ssms

Вопрос:

Microsoft SQL Server Management Studio 18 показывает ошибку:

CREATE VIEW должна быть единственной инструкцией в пакете

После выполнения запроса появляется следующая ошибка:

Неправильный синтаксис вокруг ключевого слова «select»

 create view revenue0 (supplier_no, total_revenue) as
    select
        l_suppkey,
        sum(l_extendedprice * (1 - l_discount))
    from
        lineitem
    where
        l_shipdate >= '1996-05-01'
        and l_shipdate < dateadd(mm,3,cast('1996-05-01' as datetime))
    group by
        l_suppkey;


select
s_suppkey,
s_name,
s_address,
s_phone,
total_revenue
from
supplier,
revenue0
where
    s_suppkey = supplier_no
    and total_revenue = (
        select
            max(total_revenue)
        from
            revenue0
    )
order by
s_suppkey
option (maxdop 2)
drop view revenue0
 

UPD. Я попытался запустить этот метод:

 create view revenue0 (supplier_no, total_revenue) as
    select
        l_suppkey,
        sum(l_extendedprice * (1 - l_discount))
    from
        lineitem
    where
        l_shipdate >= cast('1996-05-01' as datetime)
        and l_shipdate < dateadd(mm, 3, cast('1996-05-01' as datetime))
    group by
        l_suppkey;

go
select
    s_suppkey,
    s_name,
    s_address,
    s_phone,
    total_revenue
from
    supplier,
    revenue0
where
    s_suppkey = supplier_no
    and total_revenue = (
        select
            max(total_revenue)
        from
            revenue0
    )
order by
    s_suppkey;

drop view revenue0;
 

Но в результате выполнения запроса отображается ошибка:
Недопустимое имя объекта «revenue0».
Как только я не изменил свое имя. SQL все равно ругается на это имя.

UPD2. Вопрос был решен самостоятельно. Тема закрыта! Спасибо всем за ваши усилия!

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

1. Поместите слово GO после определения представления.

2. Можете ли вы сказать мне, где именно? Я не очень хорошо разбираюсь в SQL. Я буду очень благодарен!

3. group by l_suppkey; GO

4. Неправильный синтаксис вокруг конструкции «go».

5. вы не можете использовать «order by» в представлении, измените свой вид, чтобы не использовать его.

Ответ №1:

Ошибка сообщает, что CREATE VIEW должен быть единственным оператором в пакете. Пакет завершается в SQL Server ключевым словом «GO», как заявил Гордон, поэтому ваш код должен выглядеть следующим образом:

 create view revenue0 (supplier_no, total_revenue) as
    select
        l_suppkey,
        sum(l_extendedprice * (1 - l_discount))
    from
        lineitem
    where
        l_shipdate >= '1996-05-01'
        and l_shipdate < dateadd(mm,3,cast('1996-05-01' as datetime))
    group by
        l_suppkey;

GO -- right here. This ends a batch. Must be on a new line, with no semi-color, or SQL gets pissy. 

select
    s_suppkey,
    s_name,
    s_address,
    s_phone,
    total_revenue
from
    supplier,
    revenue0
where
    s_suppkey = supplier_no
    and total_revenue = (
        select
            max(total_revenue)
        from
            revenue0
    )
order by
    s_suppkey
option (maxdop 2); 

drop view revenue0;
 

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

1. Я тестирую «Тесты TPC-H на MS-SQL-Server» этот материал: ссылка . При выполнении этого запроса это должно быть: link .

2. Но у меня, с вашей поправкой, после выполнения SQL-запроса выводится пустая таблица. Время выполнения запроса составляет 0 секунд. Это ненормально.

3. Вы можете помочь переделать этот запрос, чтобы он работал: ссылка .

4. Я уже всю голову сломал с ним. Но этот конкретный запрос не хочет работать. Все остальные работают.

50 / 50 / 6

Регистрация: 16.05.2012

Сообщений: 232

1

Создание функции для определения скидки

12.01.2015, 21:38. Показов 7510. Ответов 5


Студворк — интернет-сервис помощи студентам

Необходимо написать функцию, которая в зависимости от стоимости покупки определяет скидку. Не представляю, как это можно сделать на T-SQL.

10000> 2%
40000> 3%
100000> 5%

На вход поступает FLOAT — стоимость покупки, на выходе FLOAT — скидка поделенная на 100.

0

1312 / 944 / 144

Регистрация: 17.01.2013

Сообщений: 2,348

12.01.2015, 21:59

2

Функция называется CASE

0

T2skler

50 / 50 / 6

Регистрация: 16.05.2012

Сообщений: 232

13.01.2015, 22:50

 [ТС]

3

UP!

T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
CREATE FUNCTION dbo.testF(@n1 int)
RETURNS INT
BEGIN
    DECLARE @n2 INT
      CASE 
         WHEN n1 >= 10000 AND n1 < 40000  THEN @n2=2
         WHEN n1 >= 40000 AND n1 < 100000 THEN @n2=3
         WHEN n1 >= 100000 THEN @n2=5
         ELSE @n2=0
      END
    return (@n2)
END

Я пытался Помогите функцию дописать, курсач из-за этого висит мёртвым грузом(

0

cygapb-007

1312 / 944 / 144

Регистрация: 17.01.2013

Сообщений: 2,348

13.01.2015, 23:07

4

Лучший ответ Сообщение было отмечено T2skler как решение

Решение

Если уж обязательно функцию (хотя не понимаю, зачем), то примерно так:

T-SQL
1
2
3
4
5
6
7
8
9
10
11
CREATE FUNCTION dbo.testF(@n1 int)
RETURNS INT
BEGIN
   RETURN 
      CASE 
         WHEN @n1 <  10000 THEN 0
         WHEN @n1 <  40000 THEN 2
         WHEN @n1 < 100000 THEN 3
         ELSE 5
      END
END

1

50 / 50 / 6

Регистрация: 16.05.2012

Сообщений: 232

14.01.2015, 15:33

 [ТС]

5

А кто подскажет, что за сообщение об ошибке: инструкция create function должна быть единственной в пакете?

0

4 / 4 / 1

Регистрация: 11.01.2015

Сообщений: 18

14.01.2015, 16:15

6

Это значит — кроме функции никаких других строк в запросе быть не должно.

0

Всякий раз, когда я запускаю это вместе с другими инструкциями SQL, он выдает ошибку:

CREATE FUNCTION ‘должен быть первым оператором в пакете запроса

Однако всякий раз, когда я выполняю его один (без SELECT * FROM CUSTOMER в моем случае это работает)

   SELECT * FROM CUSTOMER;

   create function udfLogin
    (@username nvarchar(100), @password nvarchar(100)) 
    returns int as
    begin
      if exists(select 1 from CUSTOMER where Username = @username and [Password] = @password)
        return 1
      return 0;
    end

3 ответа

Лучший ответ

Вы должны отделить каждую партию кода с помощью ключевого слова GO.

SELECT * FROM CUSTOMER
 GO
   create function udfLogin
    (@username nvarchar(100), @password nvarchar(100)) 
     returns int as
     begin
      if exists(select 1 from CUSTOMER where Username = @username and 
      [Password] = @password)
       return 1
     return 0;
   end
Go


1

Mehrnoosh
27 Мар 2018 в 11:27

Как следует из сообщения об ошибке, оператор CREATE FUNCTION должен быть первым оператором в пакете запроса. Перед оператором CREATION FUNCTION не должно быть других операторов, которые сделали бы его не первым оператором в пакете запроса. Как следует из сообщения, чтобы избежать этой ошибки, оператор CREATE FUNCTION должен быть первым оператором в пакете запроса.

SQL выполняет инструкцию как пакет запроса.

Правила использования пакетов

Следующие правила применяются к использованию пакетов:

Операторы CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER и CREATE VIEW нельзя объединять с другими операторами в пакете. Оператор CREATE должен запустить пакет. Все остальные операторы, которые следуют в этом пакете, будут интерпретированы как часть определения первого оператора CREATE.


0

Karthik Venkatraman
27 Мар 2018 в 11:37

Вы должны включить разделитель партии, например, Go

SELECT * FROM CUSTOMER
GO
   create function udfLogin
    (@username nvarchar(100), @password nvarchar(100)) 
    returns int as
    begin
      if exists(select 1 from CUSTOMER where Username = @username and [Password] = @password)
        return 1
      return 0;
    end
Go


2

Mazhar
27 Мар 2018 в 11:26

Программирование
Базы данных

Пакеты
и язык управления заданиями

Язык TransactSQL позволяет
сгруппировать последовательность операторов в один пакет, который может
выполняться либо интерактивно, либо как файл операционной системы. Пользователь
может также использовать конструкции языка управления заданиями, имеющиеся в TransactSQL, для построения программ из
отдельных операторов.

В этой главе рассматриваются следующие темы:

·      
дается общий обзор пакетов и языка управления
заданиями;

·      
приводятся правила для построения пакетов;

·      
показывается, как использовать язык управления
заданиями.

Что такое пакеты и язык
управления заданиями ?

До сих пор в данном руководстве рассматривались примеры, в
которых выполнялся лишь один оператор. Пользователь задавал отдельные
операторы, которые непосредственно выполнялись SQL Сервером с
последующей выдачей результатов (интерактивный режим). Но SQL Сервер может
выполнить по очереди сразу несколько операторов, объединенных в пакет
(программу), как в интерактивном режиме, так и в пакетном режиме, когда задание
хранится в виде файла.

Пакет (набор) SQL операторов заканчивается специальной
командой, которая сообщает SQL Серверу о необходимости выполнения всех операторов в пакете.
Такой командой в специальной утилите SQL Сервера isql является команда “go” (выполнить), которая указывается в отдельной строке. Более
детально утилиты рассматриваются в справочном
руководстве по утилитам SQL Сервера.

Вообще говоря, пакет может состоять из одного оператора, но
обычно в пакет объединяются несколько операторов. Очень часто пакет хранится
как файл операционной системы и затем вызывается на исполнение утилитой isql.

В языке TransactSQL предусмотрены специальные
ключевые слова, которые собственно и образуют язык управления заданиями и
которые позволяют пользователю влиять на последовательность выполнения
операторов. Команды языка управления можно использовать как в отдельных
операторах, так и в пакетах, а также в сохраненных процедурах и триггерах.

Без команд управления отдельные SQL операторы выполняется последовательно
в порядке их поступления. Исключение здесь составляют коррелированные запросы,
которые обсуждались в главе 5 “Подзапросы: использование запросов внутри других
запросов”. Команды управления позволяют изменять последовательность выполнения
операторов в зависимости от получаемых результатов с помощью конструкций,
используемых в языках программирования.

Такие конструкции, как ifelse,
предназначенная для ветвления по условию, и while,
предназначенная для циклического выполнения, позволяют управлять последовательностью
выполнения SQL
операторов. Язык управления заданиями, включенный в TransactSQL, по существу, превращает
стандартный  SQL в язык программирования очень
высокого уровня.

Правила составления
пакетов

В пакет можно включать только определенные SQL операторы. При составлении пакетов
следует придерживаться следующих правил:

·       Следующие
команды нельзя включать в пакет
вместе с другими операторами: creat procedure (создать процедуру), creat rule (создать правило), creat default (создать значение по
умолчанию), creat trigger (создать триггер), creat view (создать вьювер);

·       Следующие
команды можно включать в пакет: creat database (можно создать базу данных, но из того же пакета нельзя
обращаться к ее объектам), creat table (создать таблицу), creat index (создать индекс);

·       Правила и умолчания можно связывать со столбцами, но нельзя сразу
использовать в одном и том же пакете. Например, вызов процедур
sp_bindrule (присоединить
правило) и sp_bindefault (присоединить значение по умолчанию) нельзя располагать
в одном пакете с оператором insert, который
использует эти правила и умолчания;

·       Команда
use (использовать базу данных) должна
содержаться в пакете, который выполняется перед пакетом, в котором
располагаются операторы, обращающиеся к 
объектам этой базы;

·       Нельзя
выполнить команду drop (удалить), а
затем вновь создать тот же объект в этом же пакете;

·       Все
опции, установленные в пакете с помощью команды set (установить), начинают действовать только после
окончания выполнения этого пакета. Можно включить команду set и запросы к таблицам в один пакет, но опции,
установленные этой командой, не будут действовать во время выполнения этих
запросов.

Примеры использования пакетов

В этом разделе приводятся примеры, иллюстрирующие
использование пакетов с утилитой isql, которая имеет
специальную команду “go
для запуска пакета на исполнение. В следующий пакет включены два оператора
выбора:

select
count(*) from titles

select
count(*) from authors

go

 ———————

18

 ———————-

23

(Выбрана 1
строка)

Можно в одном пакете создать таблицу и сразу обратиться к
ней. В следующем примере пакета создается таблица, затем в нее вставляется
строка, после чего эта строка выбирается из таблицы:

create table
test

   (column1 char(10), column2 int)

insert test

  values («hello», 598)

select * from
test

go

(Выбрана 1
строка)

column1  column2

———   ———

hello           598

(Выбрана 1
строка)

Команда creat view (создать вьювер) должна быть
единственной командой в пакете. В следующем пакете, состоящем из одного
оператора, создается вьювер:

creat view
testview as

select column1 from test

go

Команду use можно
включать в пакет вместе с другими операторами, если эти операторы обращаются к
базе данных, которая была текущей перед вызовом пакета. В следующем примере
происходит выборка из таблицы базы данных master, а затем
открывается база данных pubs2. Здесь предполагается, что база данных master была текущей перед вызовом
пакета. После выполнения этого пакета текущей становится база данных pubs2.

select
count(*) from sysdatabase

use pubs2

go

——————

     9

(Выбрана 1
строка)

Команду drop (удалить
объект) можно включать в пакет вместе с другими операторами, если в том же
пакете уже не нужно будет обращаться к удаляемому объекту или вновь создавать
его. В следующем примере показан пакет, состоящий из оператора drop и оператора select:

drop table
test

select
count(*) from titles

go

———————-

    18

(Выбрана 1
строка)

Если в пакете где-нибудь имеется синтаксическая ошибка, то в
нем не будет выполнен ни один оператор. Например, в следующем пакете имеется
опечатка в последнем операторе, поэтому в результате появляется сообщение об
ошибке:

select
count(*) from titles

select
count(*) from authors

slect count(*)
from publishers

go

Msg 156, Level 15, State 1:

SQL Server ‘MAGOO’, LIne 3:

Incorrect syntax near the keyword ‘count’.  (Неправильная команда около слова ‘count’).

Пакеты, в которых нарушены правила их составления, также
вызывают сообщение об ошибке. Далее приводятся примеры неправильных пакетов:

create table
test

    (column1 char(10), column2 int)

insert test

    values («hello», 598)

select * from
test

create view
testview as select column1 from test

go

Msg 111, Level 15, State 3:

Server ‘hq’, Line 6:

CREATE VIEW must be the first command in a query batch.                                                     (Команда создания вьювера должна
быть первой в пакете.)

create view
testview as select column1 from test

insert
testview values («goodbye»)

go

Msg 127, Level 15, State 1:

Server ‘hq’, Procedure ‘testview’, Line 3:

This CREATE may only contain 1 statement. (Команда создания вьювера должна
быть  единственной в пакете.)

Следующий пакет будет работать только в том случае, если
текущей базой данных будет база данных, указанная в операторе use. Если же он будет запущен из другой базы данных, например
master, то будет выдано сообщение об ошибке.

use pubs2

select * from
titles

go

Msg 208, Level 16, State 1:

Server ‘hq’, Line 2:

Invalid object name ‘titles’.     (Неправильный объект ‘titles’.)

drop table
test

create table
test

(column1
char(10), column2 int)

go

Msg 2714, Level 16, State 1:

Server ‘hq’, Line 2:

There is already an object named ‘test’ in the
database.                        
                          

 (В базе данных уже имеется объект
с  названием ‘test’.)

Пакетные файлы

Пакет можно сохранить в виде файла операционной системы, а
затем вызвать его на исполнение утилитой isql. Файл может
содержать несколько пакетов, каждый из которых заканчивается ключевым словом “go”.

Например, следующий файл содержит три пакета:

use pubs2

go

select
count(*) from titles

select
count(*) from authors

go

create table
test

   (column1 char(10), column2 int)

insert test

   values («hello», 598)

select * from
test

go

При выполнении этого файла утилитой isql
получаются следующие результаты:

————-

           18

(Выбрана 1
строка)

————-

           23

(Выбрана 1
строка)

(Выбрана 1
строка)

column1      column2

———    ———

hello              598

(выбрана 1
строка)

В справочном руководстве по утилитам SQL Сервера в разделе об утилите isql приводится информация о зависимости выполнения пакетных
файлов от операционного окружения (среды).

Язык управления заданиями

Команды языка управления заданиями можно использовать как в
интерактивном режиме, так и в пакетном, а также в сохраненных процедурах.
Ключевые слова языка управления заданиями и их значение приведены в следующей
таблице:

Таблица 13-1: Ключевые слова языка управления заданиями

Ключевое
слово

Функциональное
назначение

if

Определяет
условное выполнение.

else

Определяет
альтернативную ветвь выполнения, если условие, указанное в if ложно.

Begin

Начало
блока операторов.

end

Конец
блока операторов.

While

Циклическое
выполнение операторов, пока условие, указанное в while истинно.

Break

Принудительный
выход из цикла.

continue

Повторить
выполнение цикла while.

Declare

Объявление
локальной переменной.

goto label

Переход
на метку (label),
которая расположена в блоке операторов.

Return

Безусловный
выход.

Waitfor

Установить
задержку на выполнение команды.

Print

Вывести
на экран сообщение, которое указано пользователем или хранится в локальной
переменной.

Raiserror

Вывести
на экран сообщение об ошибке, указанное пользователем или хранящееся в
локальной переменной, и установить глобальную переменную @@error (ошибка).

/* comment */

Внести
комментарий (комментарий можно указать в любом месте SQL оператора).

Условный оператор ifelse

Ключевое слово if (если),
независимо от своего дополнения else (иначе),
служит для указания условия, которое определяет нужно ли выполнять следующий
оператор. Следующий оператор выполняется, если это условие истинно, т.е. если
его значение равно TRUE
(истина).

Ключевое слово else служит
для указания альтернативного SQL оператора, который выполняется, если условие, указанное в
конструкции if оказалось
ложным (FALSE).

Условный оператор имеет следующий синтаксис:

if булевское_выражение

оператор

[else [if булевское_выражение]

оператор ]

Булевское выражение это выражение, значением которого
является истина (TRUE) или ложь (FALSE). Оно может состоять из названий
табличных столбцов и констант, соединенных арифметическими или булевскими
операциями, или подзапросов, если эти подзапросы возвращают одно (скалярное)
значение. Если булевское выражение содержит оператор выбора select, то этот оператор должен быть заключен в скобки и
должен возвращать скалярное (невекторное) значение.

Далее приводится пример условного оператора, который
содержит только условие if и
одну команду:

if exists (select postalcode from authors

         where postalcode = ‘94705’)

print
«Berkeley author»

В этом примере будет выводиться сообщение “Berkeley author”, если почтовые
индексы некоторых авторов из таблицы authors равны
“94705”. Оператор выбора в этом примере возвращает скалярное значение, которое
равно либо TRUE либо FALSE, поскольку перед ним
указано ключевое слово exists (существует).
Ключевое слово exists действует здесь точно также,
как и в подзапросах (см. главу 5 “Подзапросы: использование запросов внутри
других запросов”).

В следующем примере используются оба ключевых слова if и else. Здесь
проверяется наличие объектов, созданных пользователями, которым присваиваются
идентификационные номера, большие 50. Если такие объекты существует, то они
выбираются из таблицы в конструкции else и
для каждого из них указывается название, тип и номер.

if (select max(id) from
sysobjects) < 50

   print «There are no user-created
objects in this database.»

else

   select name, type, id from sysobjects

   where id > 50 and type = «U»

(Выбрана 1
строка)

 name           type    id

————   
—————

 authors  U 1088006907 

 publishers             U 1120007021 

 roysched               U 1152007135 

 sales                       U 1184007249 

 titleauthor    U
1216007363 

 titles                       U 1248007477 

 stores          U 1280007591 

 discounts              U 1312007705 

 test                         U 1648008902

(Выбрано 9
строк)

Условный оператор часто используется в сохраненных
процедурах для проверки наличия некоторого параметра.

Условие проверки может указываться внутри другого условия
либо в части if либо в
части else. Условие проверки должно иметь скалярное значение. В
каждой части условного оператора может быть только по одному SQL оператору. Чтобы указать несколько SQL операторов,
необходимо использовать операторные скобки beginend. Максимальное число вложенных друг в друга условий
проверки if зависит
от сложности операторов выбора (или других языковых конструкций), которые
используются в условном операторе.

Операторные скобки beginend

Ключевые слова begin и
end используются как операторные скобки для выделения единого
блока операторов, который может использоваться, например, в условном операторе.
Последовательность операторов, заключенная в скобки begin и end, называется операторным блоком.

Конструкция beginend имеет следующий вид:

begin

     блок операторов

end

Рассмотрим следующий пример:

if (select avg(price) from
titles) < $15

begin

   update titles

   set price = price * 2

   select title, price

   from titles

   where price > $28

end

В этом примере без ключевых слов begin и end условие
if относилось бы только к первому SQL оператору
этого блока. Второй и последующие операторы выполнялись бы независимо от
выполнения этого условия.

Операторный блок beginend можно включать внутрь другого
операторного блока beginend.

Циклический оператор while и команды breakcontinue

Команда while (до
тех пор, пока) используется для циклического (повторного) выполнения оператора
или блока операторов. Операторы выполнятся до тех пор, пока истинно указанное
условие.

Эта команда имеет следующий вид:

while булевское_выражение

оператор

В следующем примере операторы select и update будут
выполняться в цикле, пока средняя цена книги будет меньше $30:

while (select
avg(price) from titles) < $30

begin

   select title_id, price

   from titles

   where price > $20

   update titles

   set price = price * 2

end

(Выбрано 0
строк)

title_id        
price

——         
——-

PC1035    22.95

PS1372    21.59

TC3218    20.95

(Выбрано 3
строки)

(Выбрано 10
строк)

(Выбрано 0 строк)

title_id        
price

——         
——-

BU1032   39.98

BU1111   23.90

BU7832   39.98

MC2222  39.98

PC1035    45.90

PC8888    40.00

PS1372    43.18

PS2091    21.90

PS3333    39.98

TC3218    41.90

TC4203    23.90

TC7777    29.98

(Выбрано 12
строк)

(Выбрано 18
строк)

(Выбрано 0
строк)

Команды break (прервать)
и continue (продолжить) управляют
последовательностью выполнения операторов внутри цикла while.
Команда break прекращает
выполнение цикла. После этого управление передается оператору, следующему за
ключевым словом  end,
которое указывает на конец цикла. Команда continue передает
управление на начало цикла, поэтому все операторы, расположенные внутри цикла и
следующие за этой командой, выполняться не будут. Командам break и continue часто
предшествует проверка некоторого условия.

Синтаксис команд break и
continue имеет следующий вид:

while булевское_выражение

   begin

оператор

    ….

[оператор]

break

[оператор]

    ….

continue

    ….

[оператор]

   end

Далее приводится пример использования команд while, break, continue и if, в
котором производится действие, обратное инфляционному действию предыдущего
примера. До тех пор пока средняя цена книги остается большей $20, все цены уменьшаются наполовину.
Затем выбирается максимальная цена. Если она меньше 40 долларов, то происходит
выход из цикла, в противном случае цикл выполняется снова. Команда continue не допустит выполнение оператора вывода (печати) print, если
средняя цена меньше $20. После окончания цикла while в этом примере выводится список самых дорогих книг и
информационное сообщение «Not Too Expensive» (Не очень дорого).

while (select
avg(price) from titles) > $20

begin

    update titles

        set price = price / 2

    if (select max(price) from titles) <
$40

        break

    else

        if (select avg(price) from
titles)
< $20

            continue

    print «Average price still over
$20»

end

select
title_id, price from titles

    where price > $20

print
«Not Too Expensive»

Average price still over $20

title_id         
price 

———       
——-

PC1035       
22.95 

PS1372       
21.59 

TC3218       
20.95 

(Выбрано 3 строки)

Not Too Expensive

Если циклы while вложены друг в
друга, то команда break возвращает управление в
наименьший внешний цикл, который содержит данный цикл. После этого
возобновляется выполнение этого внешнего цикла с самого начала.

Оператор declare и локальные переменные

Переменная — это объект, которому присваивается некоторое
значение. Это значение может изменяться в процессе исполнения пакета или
сохраненной процедуры, в которых используется эта переменная. У SQL Сервера имеется два вида
переменных: локальные и глобальные. Локальные переменные определяются
пользователем, в то время как глобальные переменные являются системными и
определяются заранее.

Для задания локальных переменных используется ключевое слово
declare (объявить), после которого следует указать название
переменной, ее тип. После этого переменной можно присвоить начальное значение с
помощью оператора выбора. Локальные переменные можно использовать только в том
пакете или процедуре, в которых они объявлены.

Локальные переменные часто используются в пакетах или
процедурах как счетчики циклов в операторе while, а также внутри
операторного блока ifelse. Когда
переменные используются в сохраненной процедуре, они должны быть объявлены как
автоматические для неинтерактивного использования во время выполнения
сохраненной процедуры.

Названия локальных переменных должны начинаться со знака
“@”
и отвечать правилам, установленным для идентификаторов. Для каждой локальной
переменной нужно указать ее тип, который может быть задан пользователем или
определяться системой, но не совпадать ни с одним из системных типов text, image, sysname.

Объявление локальных переменных имеет следующий вид:

declare
@название_переменной   тип_данных

[,@название_переменной 
тип_данных] …

После объявления переменной она имеет значение NULL. Чтобы присвоить ей
значение следует использовать оператор выбора. Этот оператор имеет следующий
синтаксис:

select
@название_переменной = { выражение | (оператор_выбора) }

     [,
@название_переменной = { выражение | (оператор_выбора) } … ]

[from конструкция]
[where конструкция] [group by конструкция]

[having конструкция]
[order by конструкция]
[compute конструкция]

Локальные переменные должны объявляться в том же пакете или
процедуре, в которых они используются.

Оператор выбора, с помощью которого переменной присваивается
значение обычно возвращает одно значение. Подзапрос, который возвращает
значение для локальной переменной должен
возвращать только одно значение. Далее приводятся несколько примеров
присваивания значений переменным:

declare
@veryhigh money

select
@veryhigh = max(price)

   from titles

if @veryhigh
> $20

   print «Ouch!»

declare @one
varchar(18), @two varchar(18)

select @one =
«this is one», @two = «this is two»

if @one =
«this is one»

   print «you got one»

if @two =
«this is two»

   print «you got two»

else print
«nope»

declare
@tcount int, @pcount int

select @tcount
= (select count(*) from titles),

   @pcount = (select count(*) from publishers)

select @tcount, @pcount

Если оператор выбора возвращает более одного значения, то
переменной присваивается последнее возвращаемое значение.

С точки зрения эффективного использования памяти и времени
лучше использовать оператор:

select @a=1, @b=2,
@c=3

по сравнению с оператором:

select @a=1

select @b=2

select
@c=3

То же правило применимо к оператору declare.
Гораздо более эффективно выполняется оператор:

declare @a
int, @b char(20), @c float

по сравнению с последовательностью операторов:

declare @a int

declare @b
char(20)

declare
@c float

Оператор выбора, который присваивает значение локальной
переменной, можно использовать только для этой цели. Его нельзя использовать
для выборки данных из таблицы пользователя. В следующем примере первый оператор
выбора присваивает значение локальноц переменной @veryhigh, но для вывода ее значения
необходимо использовать второй оператор выбора:

declare
@veryhigh money

select
@veryhigh = max(price)

   from titles

select
@veryhigh

Если оператор выбора, который присваивает значение
переменной, возвращает более одного значения, то переменной присваивается
последнее возвращаемое значение. В следующем примере переменной присваивается
последнее возвращаемое значение аванса из таблицы titles:

declare @m
money

select @m =
advance from titles

select @m

(Выбрано 18 строк)

————————

               8,000.00

(Выбрана 1
строка)

Заметим, что оператор выбора, присваивающий значение
переменной, также выводит число строк, которые были при этом выбраны.

Если оператор выбора, присваивающий значение переменной, не
возвращает никакого значения, то значение переменной не изменяется.

Локальные переменные могут использоваться как аргументы в
командах print и raiserror.

Переменные и неопределенное значение

После объявления локальной переменной ей присваивается неопределенное
значение NULL. Кроме того, это значение можно присвоить с помощью оператора
выбора. Предусмотрены специальные правила сравнения неопределенных значений
переменных с другими значениями.

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

Таблица 13-2: Сравнение неопределенных значений

Операции =, !=, <>

Операции <, >, <=, !<, !>

Сравнение табличного_значения
с табличным_значением

FALSE

FALSE

Сравнение табличного_значения
с выражением

TRUE

FALSE

Сравнение выражения с
табличным_значением

TRUE

FALSE

Сравнение выражения с
выражением

TRUE

FALSE

Например, в следующем примере только первое сравнение дает
положительный результат:

declare @v int, @i int

if @v = @i select «null = null, true»

if @v > @i select «null > null, true»

——————

null = null,
true

(Выбрана 1
строка)

В следующем примере из таблицы titles выбираются все строки, в которых значение аванса (advance) является неопределенным:

declare @m money

select title_id, advance

from titles

where advance = @m

title_id           
advance       

———          
—————-

MC3026            
NULL

PC9999             
NULL

Оператор declare и
глобальные переменные

Глобальные переменные являются заранее определенными
системными переменными. Названия глобальных переменных отличаются от локальных
двумя, расположенными впереди, знаками “@”, например, @@error.

В следующей таблице приводится список глобальных переменных.

Таблица 13-3: Глобальные переменные SQL Сервера

Переменная

Значение

@@char_convert

Равна 0, если не установлено преобразование алфавитов
(множества символов). Равна 1, если такое преобразование установлено.

@@client_csname

Содержит название алфавита клиента. Равна NULL, если
алфавит клиента никогда не инициализировался, в противном случае содержит
название последнего использованного алфавита.

@@client_csid

Содержит идентификатор алфавита клиента. Устанавливается в
-1, если алфавит клиента никогда не инициализировался, в противном случае
содержит идентификатор последнего использованного алфавита из таблицы syscharset.

@@connections

Равна числу зарегистрированных входов в систему (logins)
или попыток регистраций.

@@cpu_busy

Равна времени (в тактах процессора) загрузки процессора
задачами SQL Сервера, начиная с последнего старта SQL Сервера.

@@error

Равна 0, если последняя транзакция была успешно выполнена.
В противном случае, содержит последний номер ошибки, выданный системой. Эта
переменная часто используется для проверки ошибок после исполнения последнего
оператора. Оператор типа if @@error != 0 return используется для выхода при
возникновении ошибки.

@@identity

Содержит последний номер, записанный в столбец счетчика
оператором insert или select  into.
Эта переменная изменяется при вставке каждой новой строки. Если оператор
вставляет несколько строк, то данной переменной присваивается номер последней
строки. Если в изменяемой таблице нет счетчика, то данной переменной
присваивается 0.

Значение этой переменной не меняется при ошибочном
выполнении операторов вставки или при восстановлении транзакции, которая
содержит эти операторы. Значение этой переменной не восстанавливается, даже
если оператор, увеличивший ее, был ошибочным.

@@idle

Равна количеству времени (в тактах процессора), в течении
которого у SQL Сервера не было работы.

@@io_busy

Равна количеству времени (в тактах процессора), в течении
которого SQL Сервер выполнял операции ввода-вывода.

@@isolation

Указывает на уровень изоляции Transact-SQL программы. Этот
уровень может изменяться от 1 до 3.

@@langid

Указывает на идентификатор текущего языка, который берется
из таблицы идентификаторов syslanguges.langid.

@@language

Указывает на название текущего языка, который берется из
таблицы syslanguges.name.

@@maxcharlen

Указывает на максимальную длину (в байтах) символа из
мультибайтового алфавита.

@@max_connections

Указывает на максимальное число соединений, которые могут
быть установлены с SQL Сервером
в данной вычислительной среде. Пользователь может установить любое число
соединений, не превосходящее значения этой переменной, с помощью процедуры sp_configurenumber of user connections’.

@@ncharsize

Равно средней длине (в байтах) символа национального
алфавита.

@@nestlevel

Указывает на текущей уровень вложенности исполнения,
который сначала равен нулю. При каждом вызове сохраненной процедуры или
триггера из другой процедуры или триггера, уровень вложенности увеличивается
на единицу. Если будет превзойден порог, равный 16, транзакция прерывается.

@@pack_received

Указывает на число входных пакетов (packet), прочитанных SQL Сервером.

@@pack_sent

Указывает на число выходных пакетов (packet), записанных SQL Сервером.

@@pack_errors

Указывает на число ошибок, которые возникли во время
получения или пересылки пакетов.

@@procid

Содержит идентификатор выполняемой в данный момент
сохраненной процедуры.

@@rowcount

Указывает на число строк, которые обрабатывались в
последнем запросе. Эта переменная устанавливается в ноль любой командой,
которая не работает со строками, как например, оператор if.

@@servername

Содержит название данного SQL Сервера.

@@spid

Указывает серверный идентификатор текущего процесса.

@@sqlstatus

Содержит информацию о состоянии, выданную последним
оператором fetch
(вызвать).

@@textcolid

Содержит идентификатор столбца, на который ссылается
текстовый указатель, хранящийся в глобальной переменной  @@textptr. Эта переменная имеет тип tinyint.

@@textdbid

Указывает идентификатор базы данных, которая содержит
столбец, на который ссылается указатель, хранящийся в переменной @@textptr. Эта переменная
имеет тип smallint.

@@textobjid

Указывает идентификатор объекта, который содержит столбец,
на который ссылается текстовый указатель переменной @@textptr. Эта переменная имеет тип int.

@@textptr

Содержит текстовый указатель, который использовался при
последнем обращении к тестовому или графическому столбцу. Эта переменная
имеет тип binary(16). Не следует путать эту
переменную с функцией textptr.

@@textsize

Указывает на максимальное число байтов, которые можно
выбрать из текстового или графического поля оператором select. Для утилиты isql по умолчанию это значение равно
32К, но значение, принимаемое по умолчанию, зависит от программного
обеспечения клиента. Значение этой переменной для данной сессии можно
установить командой set
textsize
.

@@textts

Указывает на момент последнего обращения к текстовому
столбцу, на который указывает переменная @@textptr. Эта переменная имеет тип varbinary(8).

@@tresh_hysteresis

Указывает на минимально допустимую величину свободной
памяти, после которой необходимо активизировать порог (threshold). Эта величина, известная
также как величина гистерезиса (hysteresis), измеряется в страницах размера 2К. Она определяет
насколько близко пороги могут быть расположены в сегменте базы данных.

@@timeticks

Указывает длительность такта процессора в микросекундах.
Эта величина, конечно, является машинно-зависимой.

@@totalerrors

Указывает на общее число ошибок, возникших в процессе
передачи данных SQL Сервером.

@@total_read

Указывает на число чтений с диска, которые SQL Сервер выполнил со
времени последнего старта.

@@total_write

Указывает на число записей с диска, которые SQL Сервер выполнил со
времени последнего старта.

@@tranchained

Указывает на текущий режим транзакций TransactSQL программы. Значение этой
переменной равно 0, если установлен несвязный (unchained) режим и 1, если связный.

@@trancount

Указывает число активных транзакций текущего пользователя.

@@transtate

Указывает текущее состояние транзакции после выполнения
оператора. Но в отличии от переменной @@error, эта переменная
не очищается после выполнения каждого оператора.

@@version

Указывает дату создания текущей версии SQL Сервера.

С помощью системной процедуры sp_monitor (монитор) можно получить информацию о многих из этих
глобальных переменных. Полная информация о системных процедурах приводится в Справочном
руководстве SQL Сервера.

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

Команда перехода goto

Команда goto (перейти на)
вызывает безусловный переход на указанную пользователем метку. Эту команду
перехода и метки можно использовать в пакетах и сохраненных процедурах.
Название метки должно отвечать правилам, установленным для идентификаторов, и
должно заканчиваться двоеточием, когда оно приводится впервые. Но двоеточие не
нужно указывать, когда метка используется для ссылки в команде goto.

Эта команда имеет следующий вид:

метка:

goto метка

Далее приводится пример использования меток и команды
безусловного перехода, команды цикла while и локальной
переменной, которая используется в качестве счетчика:

declare @count
smallint

select @count
= 1

restart:

print
«yes»

select @count
= @count + 1

while @count
<=4

   goto restart

Как и в этом примере, команде перехода обычно предшествует
проверка некоторого условия с помощью команд while или if, чтобы избежать появления бесконечного цикла между
командой goto и меткой.

Команда выхода return

Команда return (возврат)
предназначена для безусловного выхода из пакета или процедуры. Она может
использоваться в любом месте пакета или процедуры. Когда она используется в
сохраненной процедуре, то ее можно дополнить аргументом для возврата состояния
вызывающей процедуре. Операторы, расположенные после оператора возврата, не
исполняются.

Эта команда имеет следующий простой вид:

return [int_выражение]

В следующем примере в сохраненной процедуре используется
оператор return вместе с условным оператором
и операторными скобками beginend:

create
procedure findrules @nm varchar(30) = null as

if @nm is null

begin

  print «You must give a user name»

  return

end

else

begin

   select sysobjects.name, sysobjects.id,
sysobjects.uid

   from sysobjects, master..syslogins

   where master..syslogins.name = @nm

   and sysobjects.uid = master..syslogins.suid

   and
sysobjects.type = «R»

end

Если процедуре findrules
(найти правила) не задается имя пользователя в качестве параметра, то команда return вызывает выход из процедуры после сообщения,
выдаваемого на экран пользователя. Если имя задано, то из соответствующих
системных таблиц выбираются все правила, принадлежащие данному пользователю.

По своему действию команда return аналогична
команде break, которая используется для
выхода из цикла.

Примеры возврата значений с помощью этой команды приводятся
в главе 14 “Использование сохраненных процедур”.

Команда вывода print

Команда print (печатать), которая
уже использовалась в предыдущих примерах, предназначена для вывода на экран
сообщений пользователя или значений локальных переменных. Локальная переменная
должна быть объявлена в том же пакете или процедуре, где она используется.
Выводимое сообщение должно быть не длиннее 255 байт.

Эта команда имеет следующий вид:

print {форматированная_строка_вывода | @локальная_переменная |

      
@@глобальная_переменная} [, список_аргументов]

Приведем пример использования этой команды:

if exists
(select postalcode from authors

   where postalcode = ‘94705’)

print
«Berkeley author»

В следующем примере команда print используется
для вывода значения локальной переменной:

declare @msg
char(50)

select @msg =
«What’s up doc?»

print @msg

В команде print можно использовать
форматные символы (placeholders).
В выводимой строке можно указать до 20 таких символов, расположенных в любом
порядке. Эти символы заменяются форматированными строками, указанными в списке
аргументов, следующими за выводимой
строкой
, когда текст сообщения передается клиенту.

Форматные символы нумеруются, чтобы можно было изменить
порядок следования аргументов, когда выводимая строка должна быть переведена на
язык с другой грамматической структурой. Форматные символы для аргументов имеют
следующий вид: %nn!.
Вначале указывается символ процентов, за которым следует целое число от 1 до
20, заканчивающееся восклицательным знаком. Целое число указывает позицию
соответствующего аргумента в строке на исходном языке. Например, “%1!”
указывает на позицию первого аргумента в строке, “%2!” второго и т.д. Такое
указание позиции аргумента позволяет корректно перевести фразу на различные
языки, даже в том случае, когда при переводе необходимо изменить порядок слов.

Например, предположим, что выдается следующее сообщение на
английском:

%1! is not allowed in %2!.  (%1! не
допускается в %2!.)

На немецком языке это сообщение будет выглядеть следующим
образом:

%1! ist in %2! nicht zulаssig.

В этом примере %1! во всех языках представляет собой один и
тот же первый  аргумент, а %2! второй
аргумент. В этом примере также можно увидеть изменение расположения аргументов,
когда фраза переводится на другой язык. Аргументы нужно нумеровать
последовательно, хотя порядок расположения аргументов может и не
соответствовать их порядковым номерам. Например, нельзя использовать 1 и 3
аргументы, когда в выводимой строке нет 2 аргумента.

Необязательный список_аргументов
может быть последовательностью переменных и констант. Аргумент может иметь
любой тип за исключением text (текстовый) и image (графический).
Аргумент конвертируется в тип char (символьный) перед
тем, как помещается в окончательное сообщение. Если аргументов нет, то исходная
строка выводится в том виде, в каком она задана и в этом случае в ней не должны
быть никаких форматных символов.

Максимальная длина выводимой строки с уже подставленными
аргументами составляет 512 байт.

Команда raiserror

Команда raiserror (возникновение
ошибки) выводит на экран пользователя сообщение об ошибке и устанавливает
системный флаг, который фиксирует факт возникновения ошибки. Как и в команде print здесь в качестве сообщения может выступать значение
локальной переменной, но в этом случае локальная переменная должна быть
объявлена в том же пакете или процедуре, где она используется. Сообщение должно
быть не длиннее 255 символов.

Команда raiserror имеет следующий
вид:

raiserror номер_ошибки

[{форматированная_строка_вывода | @локальная_переменная }]
[,список_аргументов]

[extended_value
= extended_value [{, extended_value = extended_value }…]]

Номер_ошибки запоминается
в глобальной переменной @@error, которая содержит последний номер системной или
пользовательской ошибки, выданный SQL Сервером. Номера ошибок для сообщений, которые выдаются
пользователями, должны быть больше 17000. Если номер_ошибки находится между 17000 и 19999 и выводимая строка
отсутствует или пуста (“”), то SQL
Сервер выбирает текст сообщения об ошибке из системной таблицы sysmessages базы данных master. Эти сообщения об
ошибке используются главным образом системными процедурами.

Длина форматированной_строки_вывода
самой по себе не должна превышать 255 байтов. Длина окончательного сообщения
вместе с подставленными аргументами составляет 512 байтов. Локальные переменные
используемые для вывода сообщения должны иметь тип char или varchar. Можно не указывать выводимую строку или локальную
переменную. В этом случае SQL Сервер
использует сообщение из  таблицы sysusermessages, которое соответствует указанному номеру
ошибки. Как и команде print здесь можно подставлять в
выводимую строку значения констант или переменных, задав их в качестве
аргументов.

В качестве опции можно определить дополнительные значения
ошибки для использования в Open
Client
(открытый клиент) приложении. В этом случае в команду raiserror нужно включить конструкцию extended_value (дополнительное значение). Более детальную
информацию о дополнительных значениях ошибки можно посмотреть в документации по
Open Client приложениям
или в разделе о команде raiserror в Справочном руководстве SQL Сервера.

Команду raiserror следует
использовать вместо команды print, когда необходимо
запомнить номер ошибки в переменной @@error. Например, в процедуре findrules можно
было бы использовать следующее сообщение об ошибке:

raiserror
99999 «You must give a user name»  
(
Нужно указать имя
пользователя).

Уровень строгости (severity) всех сообщений об ошибках, выдаваемых пользователями,
равен 16. Этот уровень указывает, что у пользователя возникла нефатальная
ошибка.

Сообщения пользователя в командах print и raiserror

Пользователь может выбирать сообщения из таблицы sysusermessages (системные сообщения пользователя) с помощью
системной процедуры sp_getmassage (выдать
сообщение) для их последующего использования в командах print или raiserror. Для записи сообщений в эту таблицу следует
использовать системную процедуру sp_addmassage (добавить
сообщение).

В следующем примере демонстрируется использование процедур sp_getmassage, sp_addmassage и
команды print для записи сообщений в таблицу
sysusermessages как на английском, так на немецком языке, с
последующим их использованием в сохраненной процедуре и выводом на экран:

/*

** Install
messages

** First, the
English (langid = NULL)

*/

set language
us_english

go

sp_addmessage
25001,

  «There is already a remote user named
‘%1!’ for remote server ‘%2!’.»

go

/* Then
German*/

sp_addmessage
25001,

   «Remotebenutzername ‘%1!’ existiert
bereits auf dem Remoteserver ‘%2!’.»,»german»

go

create
procedure test_proc @remotename varchar(30),

            @remoteserver varchar(30)

as

        declare @msg varchar(255)

        declare @arg1 varchar(40)

        /*

        ** check to make sure that there is
not

        ** a @remotename for the
@remoteserver.

        */

        if exists (select *

            from master.dbo.sysremotelogins l,

                master.dbo.sysservers s

            where l.remoteserverid = s.srvid

                and s.srvname = @remoteserver

                and l.remoteusername =
@remotename)

        begin

            exec sp_getmessage 25001, @msg
output

            select
@arg1=isnull(@remotename,»null»)

            print @msg, @arg1, @remoteserver

            return (1)

        end

return(0)

go

Команда waitfor

Команда waitfor (ожидать до)
предназначена задержки исполнения блока операторов, сохраненной процедуры или
транзакции до наступления указанного времени, истечения временного интервала
или наступления некоторого события.

Эта команда имеет следующий синтаксис:

waitfor {delay «время»
| time «время» | errorexit
|  processexit | mirrorexit}

Ключевое слово delay (задержка)
сообщает SQL Серверу,
что нужно ожидать до истечения указанного временного интервала. Ключевое слово time (время) сообщает SQL Серверу, что нужно ожидать до
указанного момента времени, который должен быть задан в одном из форматов типа datetime.

Однако при этом нельзя указывать календарные даты, поскольку
календарная часть даты здесь не допускается. Время задержки, которое указывается
в операторах waitfor time или waitfor delay, может
включать часы, минуты, секунды, и оно не должно быть больше 24 часов. Для
указания времени следует использовать формат “чч:мм:сс”. Например, команда waitfor time “16:23” сообщает SQL Серверу, что нужно ожидать до 16
часов 23 минут. Оператор waitfor delay “01:30”
задерживает исполнение на один час 30 минут. Форматы указания времени можно
также посмотреть в главе 8 “Добавление, изменение и удаление данных”.

Ключевое слово errorexit
(выход по ошибке) сообщает SQL
Серверу, что нужно ожидать до тех пор, пока процесс завершится
ненормально. Ключевое слово processexit (выход
по выполнению) сообщает SQL Серверу,
что нужно ожидать до тех пор, пока процесс завершится по какой-либо причине.
Ключевое слово mirrorexit (выход по
зеркалу) сообщает SQL Серверу, что нужно ожидать до тех
пор, пока не появится ошибка по чтению или записи на одном из зеркальных
(mirror) устройств.

Команда waitfor errorexit обычно
используется для удаления процесса, который закончился ошибкой, чтобы
освободить системные ресурсы. Чтобы проверить какой процесс оказался ошибочным,
следует посмотреть таблицу sysprocesses (системные
процессы) с помощью системной процедуры sp_who.

В следующем примере SQL Сервер ожидает наступления 14 часов 20 минут. Затем
обновляется таблица chess (шахматы), в которую
записывается очередной ход и исполняется сохраненная процедура sendmessage (послать сообщение), которая вставляет это
сообщение в одну из таблиц Джуди (Judy), указывая ей тем самым, что сделан очередной ход шахматной
партии. Этот пример имеет следующий вид:

begin

waitfor time
«14:20»

insert
chess(next_move)

values(‘Q-KR5’)

execute
sendmessage ‘judy’

end

Чтобы Джуди получила сообщение через 10 секунд, а не 14:20,
нужно изменить команду ожидания следующим образом:

waitfor delay «0:00:10»

После выдачи команды waitfor нельзя
использовать связь с SQL Сервером
до тех пор, пока истечет указанный промежуток времени или наступит
соответствующее событие.

Комментарии

Комментарии обычно вносятся в операторы, пакеты и
сохраненные процедуры для лучшего их понимания. Комментарий выглядит следующим
образом:

/* Текст комментария */

На длину комментариев не накладывается никаких ограничений и
они могут вносится в любое место, либо в виде отдельной строки, либо в конце
строки. Допускаются также комментарии, занимающие несколько строк, но при этом
каждая строка должна начинаться с наклонной черты (слеша) и звездочки и
заканчиваться звездочкой и слешем. Все, что находиться между символами “/*” и
“*/”, рассматривается как комментарий. Комментарии могут быть вложенными друг в
друга.

Для длинных комментариев, занимающих несколько строк,
вводится также следующее стилистическое соглашение. Комментарий должен
начинаться символами “/*”, а все последующие строки двумя звездочками “**”.
Такой комментарий, как обычно, должен заканчиваться символами “*/”. В следующем
примере можно увидеть подобный комментарий:

select * from
titles

/* A comment
here might explain the rules

** associated
with using an asterisk as

** shorthand
in the select list.*/

where price > $5

В следующем примере приводится процедура вместе с
сопровождающими ее комментариями:

/* this
procedure finds rules by user name*/

create
procedure findrules2 @nm varchar(30) = null

as if @nm is
null /*if no parameter is given*/

print
«You must give a user name»

else

begin

   select sysobjects.name, sysobjects.id,

        sysobjects.uid

   from sysobjects, master..syslogins

   where master..syslogins.name = @nm

   and sysobjects.uid = master..syslogins.suid

   and sysobjects.type = «R»

end

[ << Назад ] [ Содержание ] [ Далее >> ]

 

Понравилась статья? Поделить с друзьями:
  • Морозильная камера стинол 105q инструкция по эксплуатации
  • Ректальные свечи пимафуцин инструкция по применению
  • Перфекто люкс бальзам инструкция по применению
  • Матрасы противопролежневые с компрессором армед инструкция
  • Инструкция по охране труда для заместителя заведующего доу