Benutzer mit den meisten Antworten
Owner der jeweiligen DB abrufen

Frage
-
Hallo zusammen,
ich habe ein kleines Problem mit dem Owner diverser Datenbanken.
Bisher hatte ich mir ein Script geschrieben um über ein Cursor alle Datenbanken durchzugehen und für preventiven Support Informationen zusammen zuziehen.
Nun hat der Anbieter einer unserer eingesetzen Applikationen sein Produkt geändert und verwendet zur Versionierung jeweils einen eigenen Owner, damit stürzt mein Script ab da ich ja statt "select " from dbo.environment" nun den dbo in v1, v2a etc abändern muss.
Kann ich im Cursor zusätzlilch den Owner auslesen und diesen dann verwenden? Da ich eh dynamisches SQL generiere, wäre das dann kein Problem, nur wie bekomme ich den aktuellen Owner raus?
Viele Grüsse,
Maximilian
Antworten
-
Hallo Maximilian,
sp_msforeachdb ist auch nichts weiter als ein Cursor, den Quelltext kannst Du Dir anschauen mit:
EXEC sp_helptext 'sp_MSforeachdb' -- die "Arbeits-Prozedur" EXEC sp_helptext 'sp_MSforeach_worker'
Was die Hochkommas angeht hilft (meistens):
Schreibe zunächst die Anweisung so dass sie ohne Aufruf funktioniert / optisch passt.
Danach verdoppele die Hochkommas über Suchen (') / Ersetzen ('').Was das Abfragen angeht, verstehe ich Deine Erläuterung nicht (V1 <> V1User nicht).
Deswegen eine allgemeinere Variante, die evtl. als Vorlage dienen kann.Eine Abfrage der Datenbankbesitzer könnte mit ms_foreachdb z. B. so aussehen:
DECLARE @DbOwnerTable TABLE (DbName sysname NOT NULL, DbOwner sysname NULL); INSERT INTO @DbOwnerTable (DbName, DbOwner) EXEC sp_msforeachdb 'SELECT ''?'', SUSER_SNAME(sid) FROM [?].sys.database_principals WHERE name = N''dbo'';'; SELECT * FROM @DbOwnerTable;
Gruß Elmar
- Als Antwort markiert MaxiTesch Donnerstag, 8. August 2013 04:16
Alle Antworten
-
Hallo Maximilian,
der Besitzer ist dem Datenbankbenutzer dbo mit der ID = 1 zugeordnet,
was Du über USER_ID (od. DATABASE_PRINCIPAL_ID) bzw. USER_NAME abfragen kannst:SELECT USER_ID('dbo'), USER_NAME(1);
Andere Benutzer können zwar Mitglied der Rolle db_owner sein oder Rechte erhalten, aber sie sind nicht der Besitzer.
Wird das Konto gelöscht, das dbo bei der Erstellung zugeordnet war, kann der Besitzer verwaist sein,
was man durch ALTER AUTHORIZATION (od sp_changedbowner) korrigieren kann (und sollte).In Deinem Fall könnte der Anbieter jedoch eigene Schemas verwenden:
Objektbesitz und Trennung von Benutzer und Schema in SQL Serverwomit "Environment" mehrfach (je Schema) existieren könnte.
Welches Schema dabei das "richtige" ist, hängt von der Vergabe ab -
und sollte irgendwo gespeichert sein, da der SQL Server davon nichts weiß. -
Ergänzend zu der Antwort von Elmar und unter der Voraussetzung, dass Du speziell für dieses Produkt Skripte erstellen willst, könntest Du über die INFORMATION_SCHEMA-Views gehen und die notwendigen Infos sammeln.
Select * from INFORMATION_SCHEMA.SCHEMATA; Select * from INFORMATION_SCHEMA.TABLES;
Das erste SQL liefert die vorhandenen Schemata, das zweite die Tabellen in allen Schemata. Dort könntest Du nachschauen, in welchen Schemata es diese Tabelle in der Datenbank gibt und die Informationen inklusive Schema-Namen ablegen.
Einen schönen Tag noch,
Christoph
--
Microsoft SQL Server MVP
http://www.insidesql.org/blogs/cmu/ -
Hallo zusammen,
danke für die Infos, sehr interessant :-)
Ich habe jetzt weiter danach schauen können und habe noch eine Frage:
Im Profiler sehe ich das beim Zugriff auf Stored Procedures und Tabellen der jeweiligen Datenbank vorher der User geändert wird... EXECUTE as user = 'v2USER' ... REVERT Betreffend des nun geänderten Schema (???) kann ich einmal direkt abfragen, das andere mal muss ich den User ändern um eine Abfrage machen zu können.
Mir ist nicht ganz bewusst wie ich prüfen kann wann ich den User ändern muss und wann nicht. Geht das überhaupt? Kann ich auslesen mit welchem User ich die jeweilige Datenbank ansprechen muss?
Viele Grüsse,
Maximilian -
Hallo Maximilian,
das hängt von Deinen Berechtigungen ab und etwas von der Stored Procedure ab.
Wenn Du SysAdmin bist, kannst Du eh alle Tabellen abfragen, ohne vorher den Benutzer zu wechseln.
Wenn Du eingeschränkte Rechte hast, hängt es davon ab, ob Du das Recht hast, die Identität des Benutzers anzunehmen.
Im Zweifelsfall einfach ausprobieren; wenn Du es nicht darfst, wirst Du schon die entsprechende Meldung erhalten.
Olaf Helper
Blog Xing -
Hallo Maximilian,
ergänzend zu Olafs Antwort:
Du kannst das gleiche Muster wie die Anwendung verwenden.
Leider wirst Du das Verhalten der Anwendung analysieren müssen, welcher "Benutzer" gerade der aktuelle ist.Sinn der Übung dürfte hier weniger eine Berechtigungprüfung als das Wechseln des Schemas sein,
das mit dem Benutzer verbunden ist - mit dem (IMHO krausen ;) Gedanken so unterschiedliche
Tabellen/Prozedur je Version verwenden zu können.Gruß Elmar
-
Hallo zusammen,
irgendwie kann ich das "Problem" nicht ganz fassen...
Die Applikation weiss ja leider welches Schema zu verwenden ist, eine entsprechende Entscheidungslogik gibt es in der Applikation nicht da jede Version eine eigene Applikation ist...
Auch bekomme ich keine Meldung betreffend Permission, führe ich den Select ohne den User aus, wird mir als Meldung "Invalid object name Mitglieder" aus.
Leider bin ich nicht soweit fortgeschritten in SQL (sorry für das nerven), aber wenn ich Euch richtig verstanden habe, gibt es kein anderen Weg.
Überlege mir gerade ob es geht den Select bzw Result in eine Variable abzulegen und dann evtl prüfen ob die Variable nicht belegt ist um dann ein anderen User zu nehmen. Ist halt Try and Error :-)
Viele Grüsse,
Maximilian -
Hallo Maximilian,
ich kann anhand Deiner Beschreibung auch nur vermuten, was die Applikation da anstellt.
Evtl. sieht es wie im folgenden Skript aus.
Dort gibt es zwei Benutzer (Benutzer1/2), sowie zwei Schemas (Schema1/2).
Beide Schemas enthalten eine Tabelle1.Die Namen von Schema / Benutzer könnten gleich lauten; ich habe sie aber
abweichend gewählt damit es leichter erkennbar ist, wer da was ist.-- Leere Datenbank USE [TestDb] GO -- Benutzer1 anlegen CREATE USER [Benutzer1] FOR LOGIN [Benutzer1]; GO -- Schema2 mit Besitz Benutzer1 CREATE SCHEMA [Schema1] AUTHORIZATION [Benutzer1] CREATE TABLE Tabelle1 (id int, daten varchar(40)) GRANT SELECT, INSERT, UPDATE, DELETE ON Tabelle1 TO public; GO -- Benutzer2 anlegen CREATE USER [Benutzer2] FOR LOGIN [Benutzer2]; GO -- Schema2 mit Besitz Benutzer2 CREATE SCHEMA [Schema2] AUTHORIZATION [Benutzer2] CREATE TABLE Tabelle1 (id int, daten varchar(40)) GRANT SELECT, INSERT, UPDATE, DELETE ON Tabelle1 TO public; GO -- Benutzer1 das Schema1 als Standard zuordnen ALTER USER Benutzer1 WITH DEFAULT_SCHEMA = Schema1; GO -- Benutzer2 das Schema2 als Standard zuordnen ALTER USER Benutzer2 WITH DEFAULT_SCHEMA = Schema2; GO
Nun kann man mit EXECUTE AS jeweils die Tabelle1 ansprechen und bekommt,
die aus dem Standard-Schema des Benutzers:-- Einfügen von Daten als Benutzer1 in Tabelle1 (in Schema1) EXECUTE AS USER = 'Benutzer1'; GO INSERT INTO Tabelle1 (id, daten) VALUES (1, 'Tabelle Benutzer1'); GO REVERT; GO -- Einfügen von Daten als Benutzer2 in Tabelle1 (in Schema2) EXECUTE AS USER = 'Benutzer2'; GO INSERT INTO Tabelle1 (id, daten) VALUES (2, 'Tabelle Benutzer2'); GO REVERT; GO -- Abfrage über Benutzer 1 EXECUTE AS USER = 'Benutzer1'; GO SELECT 'Benutzer1', * FROM Tabelle1; GO REVERT; GO -- Abfrage über Benutzer 2 EXECUTE AS USER = 'Benutzer2'; GO SELECT 'Benutzer2', * FROM Tabelle1; GO REVERT; GO
Eigentlicher Sinn der Übung ist dabei, dass die Tabelle1 (oder jedes andere Objekt)
entsprechend dem Standard-Schema des aktiven Benutzers ausgewählt wird.
Sauberer wäre Schema1.Tabelle1 bzw. Schema2.Tabelle1 und man brauchte das EXECUTE AS nicht.
Wie schon gesagt, ein krauses Design... und evtl. sieht es noch etwas anders bei Dir aus.
Gruß Elmar
-
Hi Elmar,
danke für die Ausführung, das bringt LIcht in´s Dunkel bei mir :-)
Warum auch immer der Software-Entwickler in den USA sowas macht, mir macht es die Ganze Sache schwieriger...
Ich habe mir nun was anderes überlegt, ich denke das beste ist nach dem vorhandenen Principal zu schauen. Die V1 hat den Principal v1User nicht in der jeweiligen Datenbank aufgeführt, somit kann ich derzeit nur nach diesem Merkmal pro Datenbank unterscheiden und muss warten was mit v3 dann mal passieren wird.
Prinzipielle Frage, ist ein Cursor oder eher sp_msforeachdb besser zum durchgehen der Datenbanken? Ich hatte es mit der sp_msforeachdb mal versucht (weil ich so ein Muster für den DB-Namen angeben kann), aber irgendwie komme ich mit dem setzen der Hochkomma´s in Konflikt mit dem was ich meine und was die SQL Syntax will :-)
Wie kann ich den im Cursor den Principal einer Datenbank abfragen? Ich müsste ja erst mit USE [...] die DB auswählen und dann die Anfrage des Principal ausführen...
Ich hoffe das passt noch in die ursprüngliche Frage, sonst müsste ich ein neuen Thread aufmachen.
Viele Grüsse,
Maximilian -
Hallo Maximilian,
sp_msforeachdb ist auch nichts weiter als ein Cursor, den Quelltext kannst Du Dir anschauen mit:
EXEC sp_helptext 'sp_MSforeachdb' -- die "Arbeits-Prozedur" EXEC sp_helptext 'sp_MSforeach_worker'
Was die Hochkommas angeht hilft (meistens):
Schreibe zunächst die Anweisung so dass sie ohne Aufruf funktioniert / optisch passt.
Danach verdoppele die Hochkommas über Suchen (') / Ersetzen ('').Was das Abfragen angeht, verstehe ich Deine Erläuterung nicht (V1 <> V1User nicht).
Deswegen eine allgemeinere Variante, die evtl. als Vorlage dienen kann.Eine Abfrage der Datenbankbesitzer könnte mit ms_foreachdb z. B. so aussehen:
DECLARE @DbOwnerTable TABLE (DbName sysname NOT NULL, DbOwner sysname NULL); INSERT INTO @DbOwnerTable (DbName, DbOwner) EXEC sp_msforeachdb 'SELECT ''?'', SUSER_SNAME(sid) FROM [?].sys.database_principals WHERE name = N''dbo'';'; SELECT * FROM @DbOwnerTable;
Gruß Elmar
- Als Antwort markiert MaxiTesch Donnerstag, 8. August 2013 04:16