2009-10-27 3 views
6

Peut-être une question stupide mais puis-je protéger une ligne de données dans une base de données SQL Server d'être supprimé ou mis à jour sans définir les autorisations des utilisateurs?SQL: ligne de données "Write Protect" possible?

Ceci est pour une ligne de données par défaut qui peut être référencée pour ses valeurs par défaut?

Merci

+0

Pourquoi ne voulez-vous pas définir les autorisations d'utilisateur? – SLaks

+0

Probablement pas une bonne réponse mais c'est une base de données avec un seul administrateur – Belliez

Répondre

1

Une approche possible que j'ai déjà utilisé est décrit dans mon blog:

« Supposons que vous devez appliquer la règle des affaires suivantes: les contrats ne peuvent être modifiés après avoir commencé à travailler sur eux (que nous supposons que cette activité particulière opère dans le monde parfait) Vous pouvez utiliser une colonne rowversion, une calculée persistante, et une contrainte de clé étrangère pour mettre en œuvre cette règle -. Using ROWVERSION to enforce business rules

+0

C'est une technique douce. –

+0

Un peu trop pour sa situation (puisque vous auriez besoin de la colonne RowVersion pour toutes les lignes, pas seulement la première rangée qu'il essaie de protéger), mais cela fonctionnerait! –

1

Vous pouvez faire un déclencheur qui déclenche une erreur si cette ligne est mis à jour ou supprimé.

+0

Cela ne vérifiera pas les perms automatiquement – DVK

+3

Les triggers sont ignorés lors de l'exécution de la table tronquée. – sisve

+0

Vous n'avez pas besoin d'un niveau d'autorisations distinct pour tronquer la table plutôt que de supprimer toutes les lignes? Si c'est le cas, il peut être autorisé à être limité à tous les utilisateurs sauf administrateur (comme il se doit). – DVK

0

Disons que votre MyTable est en mode principal.

Placez la première ligne dans une nouvelle table MyTableReadOnly, déplacez cette table vers son propre groupe de fichiers et ne faites que lire le groupe de fichiers.

Retirez la première ligne de la MyTable

maintenant créer une vue qui

SELECT Columns From MyTableNew 
UNION 
SELECT Columns From MyTable 

tout accès par la vue. Si vous voulez mettre à jour ou supprimer de la vue, vous pouvez le faire sur MyTable et ignorer n'importe quoi pour MyTableNew. Si vous souhaitez utiliser la vue, vous pouvez utiliser les déclencheurs INSTEAD-OF.

+0

Deux problèmes avec cette approche: Vous devez conserver votre vue (par exemple, le TDD au lieu de données) si la liste des lignes restreintes change. Et vous devez créer une nouvelle vue pour chaque ensemble de perms (même inconvénient que ma propre approche comme noté peter). – DVK

0
  • Créez une deuxième table contenant des lignes ayant les mêmes ID uniques que les lignes que vous tentez de protéger.

  • Permission de cette table DEUXIÈME que vous le souhaitez

  • Ajouter un déclencheur sur la première table qui supprimera/mettre à jour les deux tables si une ligne correspondante existe dans la deuxième table.

De cette façon, sauf si vous avez une permanente sur la deuxième table, vous ne pourrez pas modifier les lignes « liées » comme déclencheur prendra fin en raison de la violation des autorisations sur la deuxième table

NOTE : Le contraste de cette méthode avec les autres méthodes principales (en utilisant VIEWs) est qu'il permet une maintenance aisée de l'ensemble des lignes "fixes" contrairement à l'approche VIEW et évite divers problèmes de performance généralement associés aux vues.

+0

Juste une note: pour répondre à la préoccupation de Simon Svensson concernant une solution différente mentionnant un déclencheur, la troncature de la table n'est pas un problème car elle nécessite des séparations séparées de la suppression de ligne. – DVK

+0

C'est bien. Il vous permet d'accorder des autorisations sur un ensemble de lignes. Cependant, pour chaque paire distincte (ensemble de lignes, permissions), vous auriez besoin d'une autre table. Par exemple, si deux utilisateurs ont des autorisations au niveau de la ligne, mais pas sur le même ensemble de lignes, vous devez disposer d'une table de contrôle distincte pour chacun. Ai-je mal compris la mise en œuvre? –

+0

Oui, c'est le cas. Mais c'est la seule approche que je connaisse ** qui utilise les permissions au niveau de la table natif **. Tout le reste nécessite des autorisations stockées dans une table (par exemple, le déclencheur vérifie votre ID utilisateur par rapport à une table contenant des rowID mappés aux autorisations, éventuellement en utilisant les groupes d'utilisateurs DB si possible ou directement aux ID utilisateur sinon). – DVK

2

pour ce faire, l'intégrité relationnelle - ne pas utiliser des déclencheurs comme ils sont toujours une vraie douleur à maintenir après (ils ont leur place, mais pas ici) Relation int l'égrité fera tout ce dont vous avez besoin. L'utilisation de l'intégrité relationnelle peut être assez élégante, mais ce que vous devez faire est légèrement contre-intuitif si facilement manqué.

Créez votre table principale, tblMain, avec une clé primaire numérique.Pour simplifier j'ai testé cela avec une table avec une colonne, intID, et je l'ai rempli avec les valeurs 0,1 et 2.

Ensuite, créez une deuxième table, tblGuard, avec une clé primaire numérique similaire. J'ai ajouté une ligne dans cette table, la valeur 1.

Maintenant le bit de logique inverse. Créer une clé étrangère sur la tblGuard tableau qui font référence à la table tblMain

ALTER TABLE [dbo].[tblGuard] ADD 
    CONSTRAINT [FK_tblGuard_tblMain] FOREIGN KEY 
    (
     [intID] 
    ) REFERENCES [dbo].[tblMain] (
     [intID] 
    ) 

La contrainte fera en sorte que la ligne avec la valeur IntID 1 ne peut pas être supprimé de la table tblMain car la table tblGuard d'intégrité référentielle exige que la valeur 1 existe dans tblMain. Cela fonctionne avec des suppressions et tronque.

+0

Cela empêche uniquement les suppressions, il ne protège pas votre ligne contre les mises à jour. L'exigence est: "protéger une ligne de données dans une base de données SQL Server d'être supprimé ou mis à jour" –

0

Je dis cela "par programme". Par exemple laissez la ligne avec id 1 toujours la ligne par défaut, puis ajoutez à toutes les requêtes UPDATE ou DELETE "WHERE id! = 1" ou faites l'équivalent dans la langue que vous utilisez pour écrire votre logique (PHP, C, VB , etc.)