none
"Default-Wert" für Spalte mit Hilfe einer Variablen setzen RRS feed

  • Frage

  • Hallo an die Community,

    der erste Beitrag ist immer der schwierigste, also geht nicht zu hart mit mir ins Gericht.

    Momentan habe ich folgende Anforderung auf dem Tisch liegen:
    Ein Endnutzer möchte aus einem ERP-System ein Vorgabewert auf ein Memotextfeld setzen

    Im ersten Schritt habe ich mir dazu gedacht, das der Kunde über eine parametrisierte Abfrage aus dem Programm den Text eingeben kann, der wiederrum an eine Variable übergeben wird und der Inhalt den Vorgabewert einer bestimmten Spalte setzt.

    Declare @Aktionstext nvarchar(max)
    
    -- CONSTRAINT entfernen
    ALTER TABLE dbo.BELEG_Extra
    Drop CONSTRAINT col_extra_AKTION_def
    
    -- CONSTRAINT hinzufügen
    ALTER TABLE dbo.BELEG_Extra
    ADD CONSTRAINT col_extra_AKTION_def
    DEFAULT @Aktionstext FOR _AKTION ;
    GO

    Versucht man das oben genannte Skript auszuführen bekommt man die Meldung das Variablen nicht erlaubt(?) sind?

    Meldung 112, Ebene 15, Status 4, Zeile 9
    Variablen sind in der ALTER TABLE-Anweisung nicht zulässig.

    Hat irgendwer eine alternative Idee? Paralell werde ich das ganze einmal mit Programminternen Mitteln prüfen.

    Vielen Dank vorab,

    M.Heitmann

    Donnerstag, 6. Juni 2013 11:08

Antworten

  • Hallo Michael,

    Stefan hat die entscheidenden Hinweise bereits gegeben. Einen wichtigen Punkt in Bezug auf die Security sowie einen möglichen Lösungsansatz möchte ich gerne noch hinzufügen:

    Security

    EXEC sp_executeSQL ist die einzige Möglichkeit, wenn man Deinem Lösungsansatz folgen möchte. Jedoch gilt es zu bedenken, dass für eine solche Aktion ALTER-Berechtigugen auf dem Objekt erforderlich sind. Würdest Du diese Möglichkeit in Betracht ziehen, können die User nicht nur DEFAULTS ändern sondern die komlette Relation ändern / löschen / Inhalte mit TRUNCATE löschen, ...

    Ich würde diesen Ansatz - obwohl gem. Deiner Vorgehensweise einzig möglich - nicht verfolgen.

    Ich würde stattdessen eine Lösung mit einer Funktion avisieren - hier gibt es keine Probleme

    Zunächst wird die Relation für die Speicherung der Konfiguration erstellt

    -- Erstellen einer Konfigurationsrelation
    CREATE TABLE dbo.configuration
    (
    	config_flag	varchar(20)			NOT NULL,
    	config_value	varchar(max)	NOT NULL,
    	
    	CONSTRAINT pk_configuration PRIMARY KEY CLUSTERED (config_flag)
    );
    GO
    
    INSERT INTO dbo.configuration (config_flag, config_value)
    VALUES
    ('default_foo_col1', 'Das ist nur ein Default');
    GO

    Nachdem die Relation erstellt wurde, kann nun die Funktion erstellt werden, die später als DEFAULT für die Relation verwendet wird.

    CREATE FUNCTION dbo.fn_GetDefault(@config_flag varchar(20)) RETURNS varchar(max)
    AS
    BEGIN
    	DECLARE	@ReturnValue	varchar(max)
    	SELECT	@ReturnValue = config_value
    	FROM	dbo.configuration
    	WHERE	config_flag  = @config_flag
    	
    	RETURN	@ReturnValue
    END
    GO

    Nachdem alle Vorarbeiten abgeschlossen sind, kann nun die eigentliche Relation erstellt werden.

    CREATE TABLE dbo.foo
    (
    	Id	int	not null	identity (1, 1),
    	col1 varchar(256)	not null	DEFAULT (dbo.fn_GetDefault('default_foo_col1'))
    	
    	CONSTRAINT pk_foo_id PRIMARY KEY CLUSTERED (Id)
    )

    So, und nun zwei Datensätze eintragen; zwischen den beiden Eintragungen wird jedoch der Standardwert geändert :)

    -- Erster Datensatz
    INSERT INTO dbo.foo DEFAULT VALUES;
    
    -- Update des Standardtextes
    UPDATE	dbo.configuration
    SET		config_value = 'Das ist jetzt der neue Text'
    WHERE	config_flag = 'default_foo_col1'
    
    -- Zweiter Datensatz
    INSERT INTO dbo.foo DEFAULT VALUES;

    Und hier das Ergebnis:

    Viel Spaß beim Experimentieren :)

    Ich habe nun - auf Grund der Komplexität - aus diesem Thema einen eigenen Blogeintrag gemacht. Er berücksichtigt alle PRO und CONS zu diesem Thema:

    http://db-berater.blogspot.de/2013/06/dynamische-standardwerte-fur-attribute.html

    Comments are wellcome :)


    Uwe Ricken

    MCM SQL Server 2008
    MCSE - SQL Server 2012
    MCSA - SQL Server 2012

    db Berater GmbH
    http://www-db-berater.de
    SQL Server Blog (german only)



    Freitag, 7. Juni 2013 05:44

Alle Antworten

  • Hallo Michael,

    einerseits ist das, was Du da machen willst, sehr gefährlich. Denn wer sagt dir, dass die User sich ihr Zeugs nicht gegenseitig überschreiben? Denn die Tabelle(n) werden ja nicht nur von diesem einen Benutzer verwendet. Zum anderen wird ein Standardwert normalerweise einmal gesetzt und dann hat sich das. Änderungen des Standardwerts, die durch Benutzer erfolgen können, würde ich nicht erlauben.

    In dem Fall sollte man eher eine Standardwerttabelle für das Eingabeformular bauen. D.h. Du hast eine Tabelle mit Formularname, BenutzerId, Feldname und Standardwert. Diesen Wert kannst Du dann im Eingabeformular des Benutzers bei Neuanlage eines Datensatzes vorgeben.

    Wenn Du das unbedingt so machen willst, müsstest Du das ALTER Statement dynamisch als String zusammenstellen und dann bspw. über sp_executesql( ... ) ausführen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Donnerstag, 6. Juni 2013 11:14
    Moderator
  • Hallo Michael,

    Stefan hat die entscheidenden Hinweise bereits gegeben. Einen wichtigen Punkt in Bezug auf die Security sowie einen möglichen Lösungsansatz möchte ich gerne noch hinzufügen:

    Security

    EXEC sp_executeSQL ist die einzige Möglichkeit, wenn man Deinem Lösungsansatz folgen möchte. Jedoch gilt es zu bedenken, dass für eine solche Aktion ALTER-Berechtigugen auf dem Objekt erforderlich sind. Würdest Du diese Möglichkeit in Betracht ziehen, können die User nicht nur DEFAULTS ändern sondern die komlette Relation ändern / löschen / Inhalte mit TRUNCATE löschen, ...

    Ich würde diesen Ansatz - obwohl gem. Deiner Vorgehensweise einzig möglich - nicht verfolgen.

    Ich würde stattdessen eine Lösung mit einer Funktion avisieren - hier gibt es keine Probleme

    Zunächst wird die Relation für die Speicherung der Konfiguration erstellt

    -- Erstellen einer Konfigurationsrelation
    CREATE TABLE dbo.configuration
    (
    	config_flag	varchar(20)			NOT NULL,
    	config_value	varchar(max)	NOT NULL,
    	
    	CONSTRAINT pk_configuration PRIMARY KEY CLUSTERED (config_flag)
    );
    GO
    
    INSERT INTO dbo.configuration (config_flag, config_value)
    VALUES
    ('default_foo_col1', 'Das ist nur ein Default');
    GO

    Nachdem die Relation erstellt wurde, kann nun die Funktion erstellt werden, die später als DEFAULT für die Relation verwendet wird.

    CREATE FUNCTION dbo.fn_GetDefault(@config_flag varchar(20)) RETURNS varchar(max)
    AS
    BEGIN
    	DECLARE	@ReturnValue	varchar(max)
    	SELECT	@ReturnValue = config_value
    	FROM	dbo.configuration
    	WHERE	config_flag  = @config_flag
    	
    	RETURN	@ReturnValue
    END
    GO

    Nachdem alle Vorarbeiten abgeschlossen sind, kann nun die eigentliche Relation erstellt werden.

    CREATE TABLE dbo.foo
    (
    	Id	int	not null	identity (1, 1),
    	col1 varchar(256)	not null	DEFAULT (dbo.fn_GetDefault('default_foo_col1'))
    	
    	CONSTRAINT pk_foo_id PRIMARY KEY CLUSTERED (Id)
    )

    So, und nun zwei Datensätze eintragen; zwischen den beiden Eintragungen wird jedoch der Standardwert geändert :)

    -- Erster Datensatz
    INSERT INTO dbo.foo DEFAULT VALUES;
    
    -- Update des Standardtextes
    UPDATE	dbo.configuration
    SET		config_value = 'Das ist jetzt der neue Text'
    WHERE	config_flag = 'default_foo_col1'
    
    -- Zweiter Datensatz
    INSERT INTO dbo.foo DEFAULT VALUES;

    Und hier das Ergebnis:

    Viel Spaß beim Experimentieren :)

    Ich habe nun - auf Grund der Komplexität - aus diesem Thema einen eigenen Blogeintrag gemacht. Er berücksichtigt alle PRO und CONS zu diesem Thema:

    http://db-berater.blogspot.de/2013/06/dynamische-standardwerte-fur-attribute.html

    Comments are wellcome :)


    Uwe Ricken

    MCM SQL Server 2008
    MCSE - SQL Server 2012
    MCSA - SQL Server 2012

    db Berater GmbH
    http://www-db-berater.de
    SQL Server Blog (german only)



    Freitag, 7. Juni 2013 05:44
  • Hallo Uwe,

    vielen Dank für diese ausführliche Beschreibung.

    Aus pers. Interesse habe ich diesen Lösungsweg ausprobiert aber nicht implementiert.
    Habe auf Möglichkeiten des ERP-Systems zurückgegriffen.

    Dort gibt es sogenannte globale Freie Felder die zur freien Verwendung bereits vom Hersteller implementiert wurden.
    Diese können nur von einem Benutzer geändert werden.

    Vielen Dank für die kompetente und schnelle Hilfe.

    M.Heimtann

    Donnerstag, 13. Juni 2013 13:13