Разное

Sql execute описание: ( EXECUTE IMMEDIATE) / Oracle SQL / Sql.ru

Содержание

Оператор EXECUTE (Microsoft Access SQL)



  • Чтение занимает 2 мин

В этой статье

Область применения: Access 2013, Office 2013Applies to: Access 2013, Office 2013

Используется для вызова выполнения процедуры.Used to invoke the execution of a procedure.

СинтаксисSyntax

EXECUTE procedure [param1[, param2[, …]]EXECUTE procedure [param1[, param2[, …]]

Оператор EXECUTE состоит из следующих частей:The EXECUTE statement has these parts:

ЧастьPart

ОписаниеDescription

procedureprocedure

Имя процедуры, которая будет выполняться.The name of the procedure that is to be executed.

param1, param2, …param1, param2, …

Значения для параметров, определяемых указанной процедурой.Values for the parameters defined by the procedure.

ПримерExample

В этом примере присваивается имя запросу CategoryList и выполняется вызов процедуры EnumFields, которую вы можете найти в приведенном примере для оператора SELECT.This example names the query CategoryList, and calls the EnumFields procedure, which you can find in the SELECT statement example.

    Sub ProcedureX() 
     
        Dim dbs As Database, rst As Recordset 
        Dim qdf As QueryDef, strSql As String 
         
        ' Modify this line to include the path to Northwind 
        ' on your computer. 
        Set dbs = OpenDatabase("Northwind.mdb") 
         
        strSql = "PROCEDURE CategoryList; " _ 
            & "SELECT DISTINCTROW CategoryName, " _ 
            & "CategoryID FROM Categories " _ 
            & "ORDER BY CategoryName;" 
         
        ' Create a named QueryDef based on the SQL 
        ' statement. 
        Set qdf = dbs.CreateQueryDef("NewQry", strSql) 
     
        ' Create a temporary snapshot-type Recordset. 
        Set rst = qdf.OpenRecordset(dbOpenSnapshot) 
     
        ' Populate the Recordset. 
        rst.MoveLast 
                 
        ' Call EnumFields to print the contents of the  
        ' Recordset. Pass the Recordset object and desired 
        ' field width. 
        Execute EnumFields rst, 15 
         
        ' Delete the QueryDef because this is a 
        ' demonstration. 
        dbs.QueryDefs.Delete "NewQry" 
         
        dbs.Close 
     
    End Sub



Метод Database.Execute (DAO) | Microsoft Docs



  • Чтение занимает 3 мин

В этой статье

Область применения: Access 2013, Office 2013Applies to: Access 2013, Office 2013

Выполняет запрос на изменение или запускает инструкцию SQL для указанного объекта.Runs an action query or executes an SQL statement on the specified object.

СинтаксисSyntax

выражение .Execute(Query, Options)expression .Execute(Query, Options)

выражение: переменная, представляющая объект Database.expression A variable that represents a Database object.

ПараметрыParameters

ИмяName

Обязательный/необязательныйRequired/optional

Тип данныхData type

ОписаниеDescription

QueryQuery

ОбязательныйRequired

StringString

OptionsOptions

НеобязательноOptional

VariantVariant

ПримечанияRemarks

Можно использовать следующие константы RecordsetOptionEnum для параметров.You can use the following RecordsetOptionEnum constants for options.

КонстантаConstant

ОписаниеDescription

dbDenyWritedbDenyWrite

Отказывает в разрешении на запись другим пользователям (только для рабочих областей Microsoft Access).Denies write permission to other users (Microsoft Access workspaces only).

dbInconsistentdbInconsistent

(По умолчанию) Выполняет несогласованные обновления (только для рабочих областей Microsoft Access).(Default) Executes inconsistent updates (Microsoft Access workspaces only).

dbConsistentdbConsistent

Выполняет согласованные обновления (только для рабочих областей Microsoft Access).Executes consistent updates (Microsoft Access workspaces only).

dbSQLPassThroughdbSQLPassThrough

Выполняет запрос SQL к серверу.Executes an SQL pass-through query. Установка этого параметра передает инструкцию SQL в базу данных ODBC для обработки (только для рабочих областей Microsoft Access).Setting this option passes the SQL statement to an ODBC database for processing (Microsoft Access workspaces only).

dbFailOnErrordbFailOnError

Выполняет откат обновлений, если возникает ошибка (только для рабочих областей Microsoft Access).Rolls back updates if an error occurs (Microsoft Access workspaces only).

dbSeeChangesdbSeeChanges

Создает ошибку во время выполнения, если другой пользователь пытается изменить данные, которые вы редактируете (только для рабочих областей Microsoft Access).Generates a run-time error if another user is changing data you are editing (dynaset-type only).

dbRunAsyncdbRunAsync

Выполняет запрос асинхронно (только для объектов ODBCDirect Connection и QueryDef).Executes the query asynchronously (ODBCDirect Connection and QueryDef objects only).

dbExecDirectdbExecDirect

Выполняет инструкцию, не вызывая перед этим функцию API ODBC SQLPrepare (только для объектов ODBCDirect Connection и QueryDef).Executes

Dynamic T-SQL и как он может быть полезен / Хабр

В наших проектах нам приходится решать различные задачи. Для решения некоторых из них мы используем dynamic T-Sql (далее по тексту dynamic sql).

Для чего нужен dynamic sql? Каждый решает для себя. В одном из проектов с помощью dynamic sql мы решили задачи построения динамичных отчетов, в других — миграцию данных. Также dynamic sql незаменим в случаях, когда требуется создать/изменить/получить данные или объекты, но значения/названия приходят в качестве параметров. Да, это может показаться абсурдом, но есть и такие задачи.


Дальше мы покажем несколько примеров, как это можно реализовать с помощью dynamic sql.

Выполнить динамическую команду можно несколькими способами:

  • С использование ключевого слова EXEC/EXECUTE;
  • C использование хранимой процедуры sp_executesql

Данные способы отличаются между собой кардинально. На небольшом примере мы постараемся пояснить, чем они отличаются.Пример кода с EXEC/EXECUTE

DECLARE @sql varchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = 'London'
SELECT @sql = ' SELECT CustomerID, ContactName, City ' +
              ' FROM dbo.customers WHERE 1 = 1 '
   SELECT @sql = @sql + ' AND City LIKE ''' + @city + ''''
EXEC (@sql)

Как видно из запроса выше, мы формируем динамическую команду. Если выполнить select @sql, то результат будет следующий:

SELECT CustomerID, ContactName, City FROM customers WHERE City = 'London'

Что же тут плохого? — Запрос отработает, и все будут довольны. Но все же, есть несколько причин, почему так делать не стоит:

  1. При написании команды очень легко ошибиться с количеством «’», т.к. необходимо указывать дополнительные «’», чтобы передать текстовое значение в запрос.
  2. При таком запросе возможны Sql инъекции (SQL Injection). Например, стоит задать значение для @city вроде такого
    set @city = '''DROP TABLE customers--'''
    

    — и результат будет печальный, т.к. операция select выполнится успешно, как и операция DROP TABLE customers.

  3. Возможна ситуация, когда у вас будет несколько переменных, содержащих коды ваших команд. Что-то типа такой EXEC(@sql1 + @sql2 + @sql3).
    Какие трудности могут возникнуть тут?

    Нужно помнить, что каждая команда отработает отдельно, хотя на первый взгляд, может показаться, что будет выполнена операция конкатенации (@sql1 + @sql2 + @sql3), а затем выполнится общая команда. Также нужно помнить, что накладывается общее ограничение на параметр команды EXEC в 4000 символов.
  4. Происходит неявное приведение типов, т.к. параметры передаются в виде строки.

Что изменится при использовании sp_executesql? – Разработчику проще писать код и его отлаживать, т.к. код будет написан практически как обычный Sql запрос.Пример кода с sp_executesql

DECLARE @sqlCommand varchar (1000)
DECLARE @columnList varchar (75)
DECLARE @city varchar (75)
SET @city = 'London'
SET @sqlCommand = 'SELECT CustomerID, ContactName, City FROM customers WHERE City =  @city'
EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city

Что же изменилось?

  1. В отличие от EXECUTE при использовании sp_executesql, не нужно никакое приведение типов, если мы используем типизированные параметры sp_executesql.
  2. Это решает проблему с дополнительными «’».
  3. Решается проблема безопасности — Sql инъекции (SQL Injection).

Для обоих подходов планы запросов кэшируются, но они отличаются. Эти отличия приведены на рисунке 1 и рисунке 2.Получение плана запроса

SELECT q.TEXT,cp.usecounts,cp.objtype,p.*, q.*, cp.plan_handle
FROM
sys.dm_exec_cached_plans cp
CROSS apply sys.dm_exec_query_plan(cp.plan_handle) p
CROSS apply sys.dm_exec_sql_text(cp.plan_handle) AS q
WHERE
q.TEXT  NOT LIKE '%sys.dm_exec_cached_plans %'
and cp.cacheobjtype = 'Compiled Plan' 
AND q.TEXT  LIKE '%customers%'

План запрос при использование Exec

План запроса при использовании sp_executesql

Также одно из преимуществ использования sp_executesql – это возможность возвращать значение через OUT параметр.

Далее приведем пример, как мы решили одну из проблем в проекте с использованием dynamic sql.

Допустим, у нас есть товар (да неважно, собственно, что это: товар, анкета на должность, персональная анкета). Смысл в том, что каждый объект имеет свой набор свойств (атрибутов), который его характеризует, а их может быть разное количество, и они будут разного типа. Как хранить в БД – это проблема архитектуры.

Для клиента нужен был отчет, который из себя представлял n строк на m столбцов. Где m и был наш набор атрибутов. Отчет собирался по группе объектов или для какого-то объекта из группы. Но смысл остается все тот же: каждый отчет содержит разное количество столбцов для каждой группы объектов.

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

  • Использовать систему отчетности, например, MS Sql Reporting Service. Создать матричный отчет, а в качестве запроса у нас будет «простой» Select. Почему мы так не сделали? В проекте не так много было отчетов, чтобы внедрять туда SSRS.
  • Использовать тот же «простой» select и на серверной стороне уже создавать DataSet необходимой «формы». Да, так задача была решена изначально, когда данных о товарах было очень мало. Как только данных стало достаточно много, то время сбора отчета стало выходит за установленный timeout.
  • Использовать Pivot в sql. Да, отличное решение, когда вы знаете, что у вас только эти атрибуты, и новых не будет. А что делать, когда количество атрибутов часто меняется. И опять же, для каждой группы объектов у нас свой набор атрибутов, мы снова вернемся к созданию процедуры для каждой группы объектов. Не очень удобное решение, не правда ли?
  • А если использовать Pivot, но добавить туда немного dynamic sql? – Да, это решение, которое имеет право на жизнь. Его мы и опишем, как пример использования dynamic sql…

Ссылка на скрипты для создания таблиц и запроса.

В основе отчета будет лежать обычный запрос:

Основной код для отчета

SELECT p.Id as ProductID, 
		p.Name as [Наименование],
		pcp.Name as PropertiesName,
		vpp.Value as Value
	FROM dbo.Products p
	INNER JOIN dbo.PropertiesCategoryOfProducts  pcp ON pcp.CategoryOfProductsId = p.CategoryOfProductsId
	INNER JOIN dbo.ValueOfProductProperty vpp ON vpp.ProductID = p.Id
		and vpp.PropertiesCategoryOfProductsId = pcp.Id
	where p.CategoryOfProductsId = @CategoryOfProductsId

Код запроса для построения отчета

SELECT p.Id as ProductID, 
		p.Name as [Наименование],
		pcp.Name as PropertiesName,
		vpp.Value as Value
	FROM dbo.Products p
	INNER JOIN dbo.PropertiesCategoryOfProducts  pcp ON pcp.CategoryOfProductsId = p.CategoryOfProductsId
	INNER JOIN dbo.ValueOfProductProperty vpp ON vpp.ProductID = p.Id
		and vpp.PropertiesCategoryOfProductsId = pcp.Id
	where p.CategoryOfProductsId = @CategoryOfProductsId

Код запроса для построения отчета
declare @CategoryOfProductsId int = 1

declare @PivotColumnHeaders nvarchar(max)=
REVERSE(STUFF(REVERSE((select '[' + Name + ']' + ',' as 'data()'
 from dbo.PropertiesCategoryOfProducts t
 where t.CategoryOfProductsId = @CategoryOfProductsId
 FOR XML PATH('')
 )),1,1,''))

if(@PivotColumnHeaders>'')
declare @PivotTableSQL nvarchar(max)
BEGIN 
	SET @PivotTableSQL = N'
	SELECT * 
	from (SELECT p.Id as ProductID, 
		p.Name as [Наименование],
		pcp.Name as PropertiesName,
		vpp.Value as Value
	FROM dbo.Products p
	INNER JOIN dbo.PropertiesCategoryOfProducts  pcp ON pcp.CategoryOfProductsId = p.CategoryOfProductsId
	INNER JOIN dbo.ValueOfProductProperty vpp ON vpp.ProductID = p.Id
		and vpp.PropertiesCategoryOfProductsId = pcp.Id
	where p.CategoryOfProductsId = @CategoryOfProductsId
		) as Pivot_Data
	PIVOT (
			MIN(Value)
			FOR PropertiesName IN (
			  ' + @PivotColumnHeaders + '
			)
	) AS PivotTable
	'

	
	EXECUTE sp_executesql  @PivotTableSQL, N'@CategoryOfProductsId int', @CategoryOfProductsId = @CategoryOfProductsId;
END

Давайте рассмотрим, что же мы тут написали:

  • Инициализируем переменную со значением нашей категории товаров — declare @CategoryOfProductsId int = 1
  • Далее нам нужно получить список колонок для нашей категории товаров, но при этом они должны быть заключены в “[]” скобки и перечислены через “,” как этого требует синтаксис функции Pivot
    Получение списка колонок для категории товаров
    declare @PivotColumnHeaders nvarchar(max)=
    REVERSE(STUFF(REVERSE((select '[' + Name + ']' + ',' as 'data()'
     from dbo.PropertiesCategoryOfProducts t
     where t.CategoryOfProductsId = @CategoryOfProductsId
     FOR XML PATH('')
     )),1,1,''))
    


    Ну а дальше все просто: при выполнении кода список колонок для функции Pivot будет подставлен из @PivotColumnHeaders


    Если выполнить select @PivotTableSQL, то мы получим тот запрос, который без использования dynamic sql нам бы пришлось писать вручную.

    Результатом выполнения данного запроса будет отчет такого вида:

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

НОУ ИНТУИТ | Лекция | Динамический SQL

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

Создание операторов динамического SQL

Операторы динамического SQL — в отличие от операторов встроенного SQL — формируются не на этапе компиляции, а на этапе выполнения приложения. Динамический SQL может применяться совместно с ODBC API или в рамках SQL/CLI, представляющего собой расширенный уровень соответствия стандарта SQL-99.

Поддержка динамического SQL на начальном уровне соответствия стандарту SQL-92 не требуется.

Операторы динамического SQL формируются как текстовые переменные.

Например:

Stmt1:='SELECT * FROM tbl1';

Для динамического формирования оператора можно выполнять последовательное объединение строк.

Операторы динамического SQL можно использовать:

  • однократно, производя за один шаг компиляцию и выполнение оператора. Будем называть такое применение одношаговым интерфейсом;
  • многократно, разделяя процесс компиляции оператора, на котором строится план выполнения, и процесс непосредственного выполнения оператора. Будем называть такое применение многошаговым интерфейсом.
Одношаговый интерфейс

одношаговый интерфейс реализуется SQL-оператором EXECUTE IMMEDIATE, который имеет в стандарте SQL-92 следующее формальное описание:

EXECUTE IMMEDIATE :variable;

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

  • оператор не может использовать INTO-переменные;
  • оператор не может использовать переменные связи.

Следующий пример иллюстрирует применение динамического SQL с одношаговым интерфейсом:

stmt_str := 'INSERT INTO ' || table_name ||
            ' values (:f1, :f2, :f3)';
EXEC SQL EXECUTE IMMEDIATE :stmt_str;
Многошаговый интерфейс

Оператор EXECUTE IMMEDIATE удобен для одноразового выполнения, но при необходимости неоднократного выполнения, например в цикле одного и того же оператора, но с различными параметрами, более эффективно использовать многошаговый интерфейс, реализуемый операторами PREPARE и EXECUTE.

При выполнении оператора PREPARE, указываемый им SQL-оператор передается в СУБД. Далее выполняется синтаксический разбор оператора и строится план выполнения. После этого при каждом выполнении оператора EXECUTE используется уже «откомпилированный» SQL-оператор, что значительно повышает производительность. Дополнительно при выполнении оператора EXECUTE на сервер передаются значения переменных связи (если они есть), используемые, в частности, для вычисления предиката фразы WHERE.

Оператор PREPARE имеет в стандарте SQL-92 следующее формальное описание:

PREPARE [ GLOBAL | LOCAL ] operator_sql FROM string_variable;

Параметр operator_sql определяет идентификатор SQL-оператора, указываемый далее для выполнения в операторе EXECUTE или для включения в курсор в операторах ALLOCATE CURSOR или DECLARE CURSOR .

Параметр string_variable указывает строку, содержащую динамически сформированный текст SQL-оператора.

Например:

stmt_str := 'INSERT INTO ' || table_name ||
            ' values (:f1, :f2, :f3)';
EXEC SQL PREPARE GLOBAL stmt1 FROM :stmt_str;

Фразы GLOBAL и LOCAL определяют область видимости оператора: GLOBAL указывает, что оператор с данным идентификатором доступен всем процессам данного сеанса работы с СУБД, а LOCAL ограничивает доступ рамками данного выполняемого модуля (значение по умолчанию).

Если создаются два одноименных оператора, но один как GLOBAL, а другой — как LOCAL, то СУБД создает два отдельных плана выполнения как для разных операторов. В противном случае при компиляции оператора с уже существующим именем просто строится новый план выполнения оператора.

Для освобождения подготовленного SQL-оператора используется оператор DEALLOCATE PREPARE, который освобождает все ресурсы, занимаемые подготовленным SQL-оператором.

Например:

EXEC SQL DEALLOCATE PREPARE GLOBAL stmt1;

Для выполнения откомпилированного SQL-оператора используется оператор EXECUTE, который в стандарте SQL-92 имеет следующее формальное описание:

EXECUTE [ GLOBAL | LOCAL ] operator_sql
   [ INTO {variable .,:} 
     | { SQL DESCRIPTOR [ GLOBAL | LOCAL ]
         descriptor_name } ]
   [ USING {variable .,:}
      | { SQL DESCRIPTOR [ GLOBAL | LOCAL ]
          descriptor_name } ]

Фраза INTO указывается в том случае, если выполняемый SQL-оператор представляет собой запрос, возвращающий одну строку.

Динамические параметры

Значения динамических параметров передаются на сервер каждый раз при выполнении откомпилированного SQL-оператора. Динамическими параметрами могут быть как переменные связи, так и INTO-переменные.

Динамические параметры можно использовать как во встроенном SQL, так и в динамическом SQL.

динамические параметры задаются в тексте SQL-оператора символами «знак вопроса». Стандарт не определяет максимально допустимое число динамических параметров. Как правило, СУБД могут иметь ограничения только на размер вводимого SQL-оператора.

Например:

stmt_str :='INSERT INTO tbl1 
                   VALUES (?, ?, ?)';
EXEC SQL PREPARE stmt2 FROM :stmt_str;

При выполнении данного откомпилированного оператора вместо динамических параметров значения будут подставляться в порядке, указанном в SQL-операторе EXECUTE или в области SQL-дескриптора.

Список значений для динамических параметров может быть указан:

  • фразой USING оператора EXECUTE — для динамических параметров, не указываемых фразой INTO откомпилированного оператора;
  • фразой INTO оператора EXECUTE — для динамических параметров, указанных во фразе INTO откомпилированного оператора.

Например:

stmt_str1 :='INSERT INTO tbl1 (f1,f2,f3)
                    VALUES (?, ?, ?)';
EXEC SQL PREPARE stmt2 FROM :stmt_str1;
EXEC SQL EXECUTE stmt2 USING :f1, :f2, :f3;

Значение переменных f1, f2 и f3 основного языка программирования будут переданы на сервер для выполнения откомпилированного оператора с идентификатором stmt2.

Возможен вариант, когда откомпилированный оператор содержит динамические параметры и во фразе INTO оператора SELECT, и в предикате.

Например:

stmt_str2 :='SELECT f1, f2, f3 
             FROM tbl1 INTO ?, ?, ? 
             WHERE f2= ?';
EXEC SQL PREPARE stmt3 FROM :stmt_str2;
EXEC SQL EXECUTE stmt3 INTO :f1, :f2, :f3
         USING :f4;

Переменные f1, f2 и f3 основного языка программирования будут использованы как INTO-переменные, а значение переменной f4 будет передано на сервер для выполнения откомпилированного оператора с идентификатором stmt3.

Обзор и примеры

EXEC SQL

В этой статье мы рассмотрим инструкцию EXEC SQL в SQL Server и рассмотрим несколько примеров.

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

Синтаксис команды EXEC в SQL Server

Ниже приведен основной синтаксис команды EXEC в SQL Server.

—Выполнение хранимой процедуры

EXECUTE | EXEC <имя хранимой процедуры>

WITH

— Строка выполнения

EXECUTE | EXEC (‘sql строка’)

WITH

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

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations’)

BEGIN

DROP TABLE Locations

END

CREATE TABLE [dbo]. [Locations] (

[LocationID] [int] NULL,

[varchar] (100) NULL

)

GO

INSERT INTO Значения местоположений (1, Richmond Road), (2, Brigade Road), (3, Houston Street)

GO

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.procedures, где name = ‘GetLocations’)

BEGIN

ПРОЦЕДУРА DROP GetLocations

END

GO

CREATE

CREATE

AS

BEGIN

выберите LocationID, LocationName из местоположений, где LocationID = @ LocID

END

GO

Выполнение хранимой процедуры

Чтобы выполнить хранимую процедуру с помощью EXEC, передайте имя процедуры и параметры, если они есть.Пожалуйста, обратитесь к приведенному ниже сценарию T-SQL для выполнения хранимой процедуры.

EXEC GetLocations @LocID = 1

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

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.процедур, где name = ‘GetLocations’)

BEGIN

DROP PROCEDURE GetLocations

END

GO

СОЗДАТЬ ПРОЦЕДУРУ [GetLocations]

(@LocID BEGIN)

int)

AS декларация

AS

выберите LocationID, LocationName из местоположений, где LocationID = @ LocID

SET @I = 2

RETURN @I

END

GO

9000retun 9_status 9000retun 9_status 9000retun 9_status2 @retunr_status = GetLocations @LocID = 1

SELECT @retunr_status AS ReturnStatus

Строка исполнительная

Чтобы выполнить строку, создайте строку и передайте ее команде EXEC SQL.Пожалуйста, обратитесь к приведенному ниже примеру, который выполняет строку.

EXEC (‘выберите LocationID, LocationName из местоположений’)

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

Создание строки из переменной и ее выполнение с помощью команды EXEC SQL может привести к появлению нежелательного кода. Есть несколько способов избежать SQL-инъекции. Мы рассмотрим эти техники в другой статье.

объявить @sql varchar (max), @ i int

set @i = 3

SET @sql = ‘выбрать LocationID, LocationName из местоположений, где LocationID =’ + cast (@i as varchar (10))

EXEC (@SQL)

Выполнение запросов на удаленном сервере

Предложение AT connected_server_name вместе с командой EXEC используется для выполнения запросов на удаленном сервере.Должен быть настроен связанный сервер, и на связанном сервере должна быть включена опция RPC Out для выполнения запросов на удаленном сервере.

См. Следующий пример выполнения запроса на удаленном сервере. Замените имя связанного сервера именем связанного сервера.

EXEC (‘выберите имя, database_id, db_name () как CurrentDB из sys.databases, где database_id <= 4') в [TEST01V]

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

Если вы хотите выполнить запрос в конкретной базе данных, используйте в запросе «USE databasename». См. Пример ниже.

EXEC (‘использовать msdb; выбрать имя, database_id, db_name () как CurrentDB из sys.databases, где database_id <= 4') в [TEST01V]

Мы также можем отправить запрос на выборку удаленному серверу, используя четырехчастную нотацию.Мы должны включить опцию Data Access на связанном сервере. См. Пример ниже.

выберите имя, database_id из [TEST01V] .master.sys.databases, где database_id <= 4

Чтобы выполнить хранимую процедуру на удаленном сервере, используйте приведенный ниже сценарий T-SQL, заменив имя связанного сервера, имя базы данных и имя хранимой процедуры.

EXEC (‘использовать testdb; EXEC TestProcedure’) в [TEST01V]

Ниже приведен пример выполнения хранимой процедуры на связанном сервере с использованием четырехчастной нотации. Здесь « TEST01V» — это имя сервера, « test » — это имя базы данных, а « dbo » — имя схемы.

EXEC [TEST01V].test.dbo.testProc

EXEC С РЕКОМЕНДУЕМЫМ

Эта опция выполнения в операторе EXEC SQL создает новый план и отменяет его после использования. Если существует существующий план процедуры, он остается в кеше. Если для процедуры нет существующего плана и использование с опцией перекомпиляции не сохранит план в кеше.

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

exec GetLocations 1 с перекомпиляцией

После выполнения вышеупомянутого сценария T-SQL я выполнил приведенный ниже сценарий для проверки кэшированного плана.

SELECT plan_handle, usecounts, cacheobjtype, objtype, size_in_bytes, text, query_plan

FROM sys.dm_exec_cached_plans

CROSS APPLY sys.dm_exec_sql_text (plan_handle)

CROSS APPLY sys.dm_exec_query_plan (plan_handle)

WHERE text LIKE ‘% GetLocations%’

См. Изображение ниже. При выполнении процедуры с опцией перекомпиляции план не сохранялся в кеше.

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

2 GO

32 GO

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

exec GetLocations 1

GO

SELECT plan_handle, usecounts, cacheobjtype, objtype, size_in_bytes, text, query_plan

FROM sys.dm_exec_cached_plans

CROSS APPLY sys.dm_exec_sql_text (plan_handle)

CROSS APPLY sys.dm_exec_query_plan (plan_handle)

WHERE text LIKE ‘% GetLocations%’

9000 9000

000

000

9000

1 WITH RECOMPILE

GO

SELECT plan_handle, usecounts, cacheobjtype, objtype, size_in_bytes, text, query_plan

FROM sys.dm_exec_cached_plans

CROSS APPLY sys.dm_exec_sql_text (plan_handle)

CROSS APPLY sys.dm_exec_query_plan (plan_handle)

WHERE text LIKE ‘% GetLocations%’

AND objtype = ‘Proc’

Пожалуйста, обратитесь к изображению ниже, чтобы увидеть набор результатов вышеуказанного запроса. Мы видим, что идентификатор плана и количество использований совпадают, а существующий план не изменился. EXEC WITH RECOMPILE не использовал существующий план в кэше, а создал новый план, использовал его и отменил.

ВЫПОЛНИТЬ С НАБОРАМИ РЕЗУЛЬТАТОВ

Этот параметр используется для изменения набора результатов хранимой процедуры или строки, выполняемой в соответствии с определением, указанным в предложении WITH RESULT SETS.

См. Следующий пример выполнения хранимой процедуры с НАБОРЫ РЕЗУЛЬТАТОВ

exec GetLocations 1

GO

exec GetLocations 1

С НАБОРАМИ РЕЗУЛЬТАТОВ

(

(ID NUMERIC (24,6), LocName varchar (50))

)

Мы можем изменить заголовки набора результатов и тип данных возвращаемого столбца, выполнив хранимую процедуру.Это похоже на использование convert (), cast () и псевдонимов столбцов в обычном сценарии T-SQL.

Если процедура или строка T-SQL возвращает более одного набора результатов, мы должны определить несколько наборов результатов в предложении WITH RESULTS SETS, в противном случае будет выдана следующая ошибка «Оператор EXECUTE завершился неудачно, потому что в предложении WITH RESULT SETS указан 1 набор результатов (s ), и оператор попытался отправить больше наборов результатов, чем это ».

См. Следующий пример, чтобы использовать предложение WITH RESULTS SETS в инструкции EXEC SQL для множественных наборов результатов, возвращаемых хранимой процедурой или строкой.В этом примере хранимая процедура возвращает два одинаковых набора результатов. Я определил два результата в предложении WITH RESULTS SETS, изменив тип данных и заголовки набора результатов в обоих наборах результатов.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.процедуры, где name = ‘GetLocations’)

BEGIN

DROP PROCEDURE GetLocations

END

GO

CREATE PROCEDURE [dbo]. [GetLocations]

(@EGLocID

int)

выберите LocationID, LocationName из Locations, где LocationID = @ LocID

выберите LocationID, LocationName из Locations, где LocationID = @ LocID

END

GO

exec GetLocations 1

С НАБОРОМ РЕЗУЛЬТАТОВ

(LocID int, LocName varchar (50)),

(ID NUMERIC (24,6), LocName varchar (50))

)

Заключение

В этой статье мы исследовали различные аспекты инструкции EXEC SQL на нескольких примерах.Если у вас есть какие-либо вопросы, пожалуйста, задавайте их в разделе комментариев ниже.

Администратор баз данных SQL Server, разработчик с большим опытом администрирования, разработки, настройки производительности, мониторинга, обеспечения высокой доступности и аварийного восстановления SQL Server

Последние сообщения Ранги Бабу (посмотреть все)

.

SQL Server выполняет команду (sp_executesql) в функции SQL

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

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

.

sql — выполнить оператор или запустить сценарий?

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

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

.

SQL Server: выполнение на LinkedServer — статьи TechNet — США (английский)


В этой статье подробно описывается использование пункта «Execute AT LinkedServer». В каком-то смысле это лучше всего, когда вы пытаетесь выполнять динамические сложные запросы к разнородным источникам данных. Есть много случаев, когда OpenQuery / OpenRowSet и квалификатор из четырех частей вызывают
может не работать в сложной конструкции SQL. Ограничение связанного сервера резко возрастет, когда вы попытаетесь манипулировать данными и писать сложные запросы с разнородными источниками данных.

↑ Вернуться к началу


↑ Вернуться к началу


Недавно мы закончили вызов удаленной хранимой процедуры («X») с удаленной машины («Y») и сценария, необходимого для извлечения данных и сохранения на удаленном сервере («Z»). Мы настроили связанный сервер, и все работало отлично. Выполнение запросов для извлечения
данные на мою машину были в порядке, но возникла проблема, когда нам нужно было выполнить хранимую процедуру, которая содержит сложные SQL-запросы с другого удаленного сервера.

Три метода, которые мы пытались выполнить на удаленном сервере, это:

  • Вызов с четырехэтапным соглашением об именах
  • Использование OpenQuery и OpenRowSet
  • Выполнить на LinkedServer

Первый метод не был успешным, поскольку существует зависимость от входящих и исходящих транзакций. Выполнение SP с использованием Execute («SQL») AT LinkedServer было успешным. Подробности проиллюстрированы в этой статье.

↑ Вернуться к началу


  • Убедитесь, что параметры RPC и RPC Out установлены на TRUE
  • MSDTC включен для выполнения распределенных запросов

Синтаксис

Выполнить сквозную команду для связанного сервера

{EXEC | ВЫПОЛНИТЬ}

({@string_variable | [N]
'строка_команды [? ] '
} [+...n]

[{, {value | @ переменная [ВЫХОД]}} [... n]]

)

[КАК {ВХОД | ПОЛЬЗОВАТЕЛЬ} =
«имя» ]

[AT connected_server_name]

[;]

Пример,

   

DECLARE @Script nvarchar (max) =

N '

<динамический сценарий sql>

';

EXECUTE (@Script) AT

INSERT <таблица> (столбцы)

EXECUTE (@Script) AT <связанный сервер>;

   

SQL может быть отдельным запросом или последовательностью операторов, динамическим SQL или полностью статическим.Связанный сервер может быть экземпляром SQL, Oracle, DB2 и т. Д. Использование Openquery, Openrowset и хранимой процедуры, состоящей из четырех частей, может работать в простой
случаи. Когда вы работаете с распределенными запросами с гетерогенным источником данных, лучше всего работает EXECUTE… AT LinkedServer. SQL Server расширяет оператор EXECUTE, чтобы его можно было использовать для отправки сквозных команд на связанные серверы. Дополнительно,
контекст, в котором выполняется строка или команда, может быть установлен явно.

↑ Вернуться к началу


Ошибка 1: объект не имеет столбцов или текущий пользователь не имеет разрешений на этот объект

«Невозможно обработать объект« <текст запроса> ». Поставщик OLE DB« <поставщик> »для связанного сервера« <сервер> »указывает, что либо у объекта есть
нет столбцов или текущий пользователь не имеет разрешений на этот объект "

OpenQuery и OpenRowset часто лучше всего использовать с простым оператором SELECT.Добавив «SET FMTONLY OFF; SET NOCOUNT ON; ’в строку SQL игнорирует проверку формата вывода и возвращает данные как есть. Команда OPENROWSET работает
то же самое, что и команда OPENQUERY, но OpenRowSet обеспечивает гибкость в создании динамических соединений.

ВЫБРАТЬ
* ИЗ
OPENQUERY (ADDBSP18, 'SET FMTONLY ON; exec MES_DW2_PROD.dbo.SPTrans_Tracs_Pull_Prashanth' '01.07.2016' ',' '31.07.2016' '' )

Причина ошибки в том, что при выполнении хранимой процедуры на связанном сервере поставщик сначала пытается определить форму результирующего набора строк.Это делается с помощью команды SET FMTONLY ON; Есть несколько способов справиться с подобными ситуациями
внутри самого SP, который избегает использования временных таблиц.

Ошибка 2: невозможно начать распределенную транзакцию

«Операция не может быть выполнена, поскольку поставщик OLE DB« SQLNCLI »для связанного сервера« X »не смог начать распределенную транзакцию»

Чтобы повторно включить команды RCP для связанного сервера:

 

exec sp_serveroption @ server = 'SERVERNAME1', @ optname = ' rpc ', @ optvalue = ' true'

exec sp_serveroption @ server = 'SERVERNAME1' , @ optname = 'rpc out' , @ optvalue = 'true'

Вызов удаленного SP с квалификатором, состоящим из четырех частей.

 

EXEC ADBSP 18 .DW_PROD.dbo. [trans_Tracs_Pull] '01.07.2016' , '31.07.2016'

Ошибка 3: диспетчер транзакций отключил поддержку удаленных / сетевых транзакций

«Операция не может быть выполнена. Провайдеру СТАРОЙ БД« SQLNCLI10 »для связанного сервера« MYSERVER »не удалось начать распределенную транзакцию. Диспетчер транзакций
отключил поддержку удаленных / сетевых транзакций.«

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

В этом случае удаленный сервер был настроен с драйвером IBM I-Series.

  • Откройте «Службы компонентов» Панель управления> Администрирование> Службы компонентов.
  • В службах компонентов щелкните правой кнопкой мыши «Мой компьютер» и выберите «Свойства» Корень консоли> Службы компонентов> Компьютеры> Мой компьютер
  • Выберите вкладку «MSDTC» (выберите соответствующий MSDTC, если он кластеризован) и нажмите «Конфигурация безопасности» в «Конфигурации транзакции»

Включите Разрешить входящий и Разрешить исходящий.

  • Перезапустите службу DTC (это должно происходить автоматически).

В приведенном ниже примере показано выполнение распределенного запроса, выполняемого на удаленном сервере, который извлекает данные и записывает их в другой удаленный экземпляр SQL.

↑ Вернуться к началу


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

OPENQUERY / OPENROWSET гарантирует, что SQL будет выполняться на удаленном сервере и только вернет результаты этого запроса на локальный сервер.Во многих случаях это можно использовать для простых операторов SQL, и набор строк не
держите в любых временных таблицах. Когда SQL становится сложным и требует запроса гетерогенного источника данных, это может стать немного громоздким. EXEC () AT похож на OPENQUERY / OPENQUERY в том, что статический / динамический SQL всегда будет выполняться на удаленном сервере.
за исключением того, что вы не можете использовать результаты локально в JOIN, но вы можете использовать их, чтобы ВСТАВИТЬ их в локальную таблицу. Кроме того, EXEC () AT позволяет вам указывать SQL в переменной, тогда как OPENQUERY не принимает переменную, которая много раз заставляет
использование динамического SQL.

Как обычно, любые отзывы приветствуются. Надеюсь, эта статья была для вас полезной!

↑ Вернуться к началу


Технет

ВЫПОЛНИТЬ (Transact-SQL)

↑ Вернуться к началу


.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *