Подтвердить что ты не робот

Вставка/обновление/удаление с помощью функции в SQL Server

Можно ли выполнить оператор Insert/Update/Delete с помощью SQL Server Functions. Я попытался с ошибкой SQL Server.

Ошибка:

Invalid use of side-effecting or time-dependent operator in 'DELETE' within a function.

AnyBody имеет любую идею, почему мы не можем использовать операторы Insert/Update/Delete с SQL Server functions.

Ожидание вашей хорошей идеи

4b9b3361

Ответ 1

Нет, вы не можете.

Из электронной документации по SQL Server:

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

Ссылка.

Ответ 2

Функции в SQL Server, как и в математике, не могут использоваться для изменения базы данных. Они предназначены только для чтения и могут помочь разработчику выполнить разделение командной строки. Другими словами, задавая вопрос, не следует изменять ответ. Когда ваша программа должна изменить базу данных, используйте хранимую процедуру.

Ответ 3

Да, вы можете!))

Я нашел один способ сделать INSERT, UPDATE или DELETE в функции с помощью xp_cmdshell.

Итак, вам нужно просто заменить код внутри переменной @sql.

CREATE FUNCTION [dbo].[_tmp_func](@orderID NVARCHAR(50))
RETURNS INT
AS
BEGIN
DECLARE @sql varchar(4000), @cmd varchar(4000)
SELECT @sql = 'INSERT INTO _ord (ord_Code) VALUES (''' + @orderID + ''') '
SELECT @cmd = 'sqlcmd -S ' + @@servername +
              ' -d ' + db_name() + ' -Q "' + @sql + '"'
EXEC master..xp_cmdshell @cmd, 'no_output'
RETURN 1
END

Ответ 4

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

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

create table MyTable
(
    ID int,
    column1 varchar(100)
)
update [MyTable]
set column1='My value'

но вы можете сделать:

declare @myTable table
(
    ID int,
    column1 varchar(100)
)

Update @myTable
set column1='My value'

Ответ 5

Да, вы можете.

Однако для этого требуется SQL CLR с разрешением EXTERNAL_ACCESS или UNSAFE и указанием строки подключения. Это явно не рекомендуется.

Например, используя Eval SQL.NET (SQL CLR, который позволяет добавлять синтаксис С# в SQL)

CREATE FUNCTION [dbo].[fn_modify_table_state]
    (
      @conn VARCHAR(8000) ,
      @sql VARCHAR(8000)
    )
RETURNS INT
AS
    BEGIN
        RETURN SQLNET::New('
using(var connection = new SqlConnection(conn))
{
    connection.Open();

    using(var command = new SqlCommand(sql, connection))
    {
        return command.ExecuteNonQuery();
    }
}
').ValueString('conn', @conn).ValueString('sql', @sql).EvalReadAccessInt()

    END

    GO

DECLARE @conn VARCHAR(8000) = 'Data Source=XPS8700;Initial Catalog=SqlServerEval_Debug;Integrated Security=True'
DECLARE @sql VARCHAR(8000) = 'UPDATE [Table_1] SET Value = -1 WHERE Name = ''zzz'''

DECLARE @rowAffecteds INT =  dbo.fn_modify_table_state(@conn, @sql)

Документация: изменение состояния таблицы в функции SQL

Отказ от ответственности: я владелец проекта Eval SQL.NET

Ответ 6

Еще одна альтернатива, использующая sp_executesql (тестируется только в SQL 2016). Как отмечалось в предыдущих сообщениях, атомичность должна выполняться в другом месте.

CREATE FUNCTION [dbo].[fn_get_service_version_checksum2]
(
    @ServiceId INT
)
RETURNS INT
AS
BEGIN
DECLARE @Checksum INT;
SELECT @Checksum = dbo.fn_get_service_version(@ServiceId);
DECLARE @LatestVersion INT = (SELECT MAX(ServiceVersion) FROM [ServiceVersion] WHERE ServiceId = @ServiceId);
-- Check whether the current version already exists and that it the latest version.
IF EXISTS(SELECT TOP 1 1 FROM [ServiceVersion] WHERE ServiceId = @ServiceId AND [Checksum] = @Checksum AND ServiceVersion = @LatestVersion)
    RETURN @LatestVersion;
-- Insert the new version to the table.
EXEC sp_executesql N'
INSERT INTO [ServiceVersion] (ServiceId, ServiceVersion, [Checksum], [Timestamp])
VALUES (@ServiceId, @LatestVersion + 1, @Checksum, GETUTCDATE());',
N'@ServiceId INT = NULL, @LatestVersion INT = NULL, @Checksum INT = NULL',
@ServiceId = @ServiceId,
@LatestVersion = @LatestVersion,
@Checksum = @Checksum
;
RETURN @LatestVersion + 1;
END;

Ответ 7

Мы не можем сказать, что возможно, что их нет, существует другой способ выполнения операции обновления в пользовательской функции. Непосредственно DML в UDF невозможен.

Ниже Query работает отлично:

create table testTbl
(
id int identity(1,1) Not null,
name nvarchar(100)
)
GO

insert into testTbl values('ajay'),('amit'),('akhil')
Go

create function tblValued()
returns Table
as
return (select * from testTbl where id = 1)
Go

update tblValued() set name ='ajay sharma' where id = 1
Go

select * from testTbl 
Go

Ответ 8

"Функции имеют доступ только к базе данных READ-ONLY". Если в функциях будут разрешены операции DML, функция будет prety похожа на хранимую процедуру.

Ответ 9

  Нет, вы не можете сделать Вставить/Обновить/Удалить.

Функции работают только с операторами select. И он имеет только доступ только для чтения базы данных.

Кроме того:

  • Функции компилируются каждый раз.
  • Функции должны возвращать значение или результат.
  • Функции работают только с входными параметрами.
  • Операторы try и catch не используются в функциях.

Ответ 10

если вам нужно запустить удаление/вставку/обновление, вы также можете запускать динамические операторы. то есть:.

declare 
    @v_dynDelete                 NVARCHAR(500);

 SET @v_dynDelete = 'DELETE some_table;'; 
 EXEC @v_dynDelete