Aufruf von UPDATE STATISTICS aus einer gespeicherten Prozedur, wenn der anrufende Benutzer keine ALTER TABLE hat

Ich habe eine App, die es Benutzern ermöglicht, große datadateien hochzuladen und dann analysiert und die data in einer SQL server 2008 R2-database speichert.

Ich möchte automatisch UPDATE STATISTICS auf der Tabelle ausführen, in die die data importiert werden, da die Benutzer Berichte über die data ausführen können und die datamenge sehr groß ist.

Der datazugriff erfolgt über gespeicherte Prozeduren und der Benutzer hat keine permissions für die Tabellen, die nur auf den gespeicherten Prozeduren ausgeführt werden.

Ich schrieb eine gespeicherte Prozedur, um einen Tabellennamen zu nehmen und sp_Executesql zu verwenden, um UPDATE STATISTICS auf dem Tabellennamen auszuführen, der übergeben wird. Sowohl der gespeicherte Proc als auch die Tabelle sind im Besitz von dbo. Ich bekomme einen Fehler, der sagt: "Kann das object nicht finden" Tabelle "weil es nicht existiert oder du keine permissions hast." Wenn ich dem Benutzer den Tisch verändere, dann geht es gut, aber ich würde es gerne vermeiden. Ich dachte, dass, wenn die Tabelle und gespeicherte proc von dem gleichen Besitzer besessen wurden dann die permissions des Benutzers ignoriert werden.

Ist es möglich, UPDATE STATISTICS irgendwie laufen zu lassen, ohne die Änderung der Tabellenberechtigung zu haben?

   

Die permissions des Benutzers können nicht ignoriert werden, wenn Sie sp_executesql . Es sei denn, Sie machen das Verfahren im Zusammenhang mit jemand anderem ausführen. Anstatt einen anderen Benutzer auszuwählen, würde ich lieber einen Benutzer ohne Login erstellen. Also lasst uns sagen, du hast einen Tisch namens dbo.farb , der Benutzer foobarblat kann nicht ALTER ( DENY ist nicht notwendig, aber es ist wirklich der Punkt):

 USE master; GO CREATE LOGIN foobarblat WITH PASSWORD = 'foobarblat', CHECK_POLICY = OFF; GO USE YourDatabase; GO CREATE USER foobarblat FROM LOGIN foobarblat; GO CREATE TABLE dbo.farb(id INT); GO DENY ALTER ON dbo.farb to foobarblat; GO 

Jetzt lassen wir uns einen versteckten Benutzer schaffen – wir können diesem Benutzer alle permissions in der Welt geben, denn niemand kann sich als Benutzer anmelden, aber für dieses Beispiel können wir ALTER auf unserem Tisch gewähren):

 CREATE USER SuperSecret WITHOUT LOGIN; GO GRANT ALTER ON dbo.farb TO SuperSecret; GO 

Jetzt können wir eine gespeicherte Prozedur schreiben, die im Kontext unseres SuperSecret Benutzers ausgeführt wird, aber von foobarblat ausgeführt werden foobarblat :

 CREATE PROCEDURE dbo.UpdateStats @tablename NVARCHAR(511) WITH EXECUTE AS 'SuperSecret' AS BEGIN DECLARE @sql NVARCHAR(MAX); SET @sql = N'UPDATE STATISTICS ' + @tablename; EXEC sp_executesql @sql; END GO GRANT EXEC ON dbo.UpdateStats TO foobarblat; 

Jetzt in einem neuen windows mit foobarblat – du solltest das problemlos ausführen können:

 EXEC dbo.UpdateStats 'dbo.farb'; 

Zusätzlich zu dem, was Aaron Bertrand sagte, werde ich eine weitere Lösung für die Mischung hinzufügen: module Signieren. Die notwendigen Schritte (in Kürze):

  • ein Zertifikat erstellen
  • importiere es in SQL server
  • Erstellen Sie eine Anmeldung aus dem Zertifikat
  • Erstellen Sie einen Benutzer aus der Anmeldung
  • permissions für den Benutzer erteilen (in diesem Fall alter table)
  • unterschreibe die gespeicherte Prozedur mit dem Zertifikat
  • gewähren Sie die Berechtigung für die gespeicherte Prozedur, wem auch immer es ausführen muss

Der Vorteil, den ich sehe, ist, dass, wenn die Prozedur läuft, werden Sie sehen, wer es tatsächlich läuft. Der Nachteil ist, dass jede Änderung der gespeicherten Prozedur erfordert, dass Sie es neu zu unterzeichnen (dh Signaturen bestehen nicht über Änderungen) und einige anfängliche Setup. Aarons Ansatz hat das Gegenteil.