it-swarm.com.de

Einfügen/Aktualisieren/Löschen mit Funktion in SQL Server

Können wir eine Insert/Update/Delete-Anweisung mit SQL Server Functions ausführen? Ich habe mit versucht, aber SQL Server-Fehler ist aufgetreten.

Error:

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

AnyBody hat eine Idee, warum wir Insert/Update/Delete-Anweisungen nicht mit SQL Server functions. verwenden können.

Warten auf Ihre gute Idee

34
Pankaj Agarwal

Nein können Sie nicht.

Aus der SQL Server-Onlinedokumentation:

Benutzerdefinierte Funktionen können nicht verwendet werden um Aktionen auszuführen, die den .__ verändern. Datenbankstatus.

Ref .

68
Mitch Wheat

Funktionen in SQL Server können, wie in der Mathematik, nicht zum Ändern der Datenbank verwendet werden. Sie sind nur zum Lesen gedacht und können dem Entwickler bei der Implementierung der Befehlsabfrage-Trennung helfen. Mit anderen Worten, das Stellen einer Frage sollte die Antwort nicht ändern. Wenn Ihr Programm die Datenbank ändern muss, verwenden Sie stattdessen eine gespeicherte Prozedur.

18
Anthony Faull

Ja, du kannst!))

Ich habe einen Weg gefunden, INSERT, UPDATE oder DELETE mit Funktion xp_cmdshell in der Funktion zu machen.

Sie müssen also nur den Code in der @sql-Variablen ersetzen.

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
11
Yurii Tsurul

Sie können Tabellen nicht von einer Funktion aus wie eine gespeicherte Prozedur aktualisieren, Sie können jedoch Tabellenvariablen aktualisieren.

Sie können dies beispielsweise in Ihrer Funktion nicht ausführen:

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

aber du kannst tun:

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

Update @myTable
set column1='My value'
4
FistOfFury

Ja können Sie.

Es erfordert jedoch SQL CLR mit EXTERNAL_ACCESS- oder UNSAFE-Berechtigung und die Angabe einer Verbindungszeichenfolge. Dies ist offensichtlich nicht empfohlen.

Verwenden Sie beispielsweise Eval SQL.NET (eine SQL-CLR, die das Hinzufügen von C # -Syntax in SQL ermöglicht.)

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)

Dokumentation: Tabellenstatus innerhalb einer SQL-Funktion ändern

Disclaimer: Ich bin der Eigentümer des Projekts Eval SQL.NET

3
Jonathan Magnan

Nein, Sie können nicht Einfügen/Aktualisieren/Löschen.

Funktionen funktionieren nur mit select Anweisungen. Und es hat nur READ-ONLY-Datenbankzugriff.

Zusätzlich:

  • Funktionen werden jedes Mal kompiliert.
  • Funktionen müssen einen Wert oder ein Ergebnis zurückgeben.
  • Funktionen funktionieren nur mit Eingabeparametern.
  • Try-and-Catch-Anweisungen werden in Funktionen nicht verwendet.
0
Majedur Rahaman

"Funktionen haben nur READ-ONLY-Datenbankzugriff" Wenn DML-Operationen in Funktionen zulässig wären, wäre die Funktion der gespeicherten Prozedur sehr ähnlich.

0
user11378203

Eine weitere Alternative ist die Verwendung von sp_executesql (getestet nur in SQL 2016 ) . Wie bereits in früheren Beiträgen bemerkt, muss Atomizität anderswo behandelt werden.

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's 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;
0
Vinicius

Wir können nicht sagen, dass es nicht möglich ist, dass es eine andere Möglichkeit gibt, Aktualisierungsvorgänge in benutzerdefinierten Funktionen durchzuführen. Direkt ist DML in UDF nicht möglich, das ist sicher.

Unter Query funktioniert einwandfrei:

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
0
Ajay Sharma