none
SQL Funktion mehrere Rückgabewerte RRS feed

  • Frage

  • Guten Tag,

    Wie kann man eine Funktion programmieren, dass einfach den Befehl "Select [test] FROM [test].[dbo].[test]" ausführt und alle ergebnisse zurückgibt.

    Mit freundlichen Grüßen,
    Webdesigner01
    Freitag, 1. März 2013 15:05

Alle Antworten

  • Hi,

    ähm. Genau so, wie Du es geschrieben hast.

    Was genau soll denn in welchem Format zurückgegeben werden?


    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

    Freitag, 1. März 2013 15:10
    Moderator
  • Guten Tag,

    Ich möchte eine Funktion schreiben, der alle Zeilen einer Spalte zurückgibt. Wie kann man das machen?

    Eine zweite Frage:

    SELECT * FROM [@database_name].[dbo].[hourly_rates]

    Wissen Sie wieso das nicht funktioniert?

    Mit freundlichen Grüßen,

    Webdesigner01


    Freitag, 1. März 2013 15:12
  • Hi,

    um alle Zeilen einer Spalte zurückzugeben, schreibt man genau das, was Du in deinem ersten Posting angegeben hast.

    SELECT <Spalte>
    FROM   <Tabelle>
    

    Objektnamen können nicht durch Parameter ersetzt werden. Also weder die Datenbank und das Schema, noch die Tabelllen- oder Spaltennamen.

    Eine Möglichkeit ist dynamisches SQL. Also die Erstellung des SQL Statements als String und das ausführen per EXEC( @Variable ) bzw. sp_executesql.

    Es sei aber die Frage erlaubt, warum Du das so machen willst. In vielen Fällen ist es unnötig und kontrakproduktiv. Schau Dir hierfür auch mal diesen Beitrag an:

      http://www.insidesql.org/blogs/frankkalis/2004/07/16/dynamisches-sql-fluch-und-segen

    Dort findest Du auch Beispiele, wie Du dynamische SQL Statements erzeugen und ausführen kannst.


    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

    Freitag, 1. März 2013 15:20
    Moderator
  • Guten Tag,

    Vielen Dank für die Antwort.

    Funktion

    ALTER FUNCTION dbo.ausgaben(@database_name As varchar(max))
    RETURNS float
    AS
    BEGIN
    RETURN(
    SELECT SUM([euro/hour] FROM [@database_name].[dbo].[ausgaben]);

    Wie würde das jetzt ausschauen?

    Mit freundlichen Grüßen,

    Webdesigner01

    Freitag, 1. März 2013 15:25
  • Hi,

    schau dir bitte den verlinkten Artikel an. Da steht das drin.

    Ein wenig Eigeninitiative solltest Du schon zeigen.


    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

    Freitag, 1. März 2013 16:00
    Moderator
  • Guten Tag

    code:

    ALTER FUNCTION dbo.ausgaben()
    RETURNS float
    AS
    BEGIN
    
     DECLARE @sql nvarchar(4000),
               @min varchar(20)
       SELECT @sql = N'Select [task_id] FROM [test].[dbo].[test]'
       EXEC sp_executesql @sql, N'@min varchar(20) OUTPUT', @min OUTPUT
    
    RETURN(
    @min
    )END;

    Wieso funktioniert das nicht?

    Error: Meldung 557, Ebene 16, Status 2, Zeile 1
    Nur Funktionen und einige erweiterte gespeicherte Prozeduren können innerhalb einer Funktion ausgeführt werden.

    Mit freundlichen Grüßen,

    Webdesigner01

    Freitag, 1. März 2013 17:27
  • Hi,

    als T-SQL Funktion geht das nicht. Siehe bspw:

      http://www.insidesql.org/blogs/frankkalis/2004/08/02/dynamisches-sql-innerhalb-einer-funktion

    Aber warum gerade eine Funktion? Das Ganze sieht mir sehr zusammengewürfelt aus. Rückgabe Float, Rückgabeparameter ist aber varchar, ein Statement, welches keinen Sinn ergibt (im Bezug auf die Rückgabe), ...

    Was genau willst Du überhaupt machen? Wenn man das weiß, kann man dir evtl. auch besser helfen.


    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

    Freitag, 1. März 2013 17:51
    Moderator
  • Guten Tag,

    Ich habe eine Funktion schreiben wollen, der mir die ausgaben berechnet und zurückgibt. Ich kenne nur leider die Funktion, wie könnte man es sonst machen?

    Mit freundlichen Grüßen,

    Webdesigner01

    Freitag, 1. März 2013 18:02
  • Hi,

    ich wollte auch mal irgendwas schreiben, was mir irgendwie irgendwas macht und mir das dann wieder irgendwie doppelt zurückgibt. Hab ich auch nicht hinbekommen :) (Nicht böse gemeint :)

    Soll heißen, so einfach drauflos "entwickelt" kann das auch nie was werden.

    Beschreib bitte mal deine Tabellenstruktur. Also die Definition der Tabelle, in der die Daten stehen.

    Gib uns dazu ein paar Beispieldatensätze und das gewünschte Ergebnis deiner Abfrage.

    Bitte gar nicht erst versuchen, das irgendwie mit Worten zu umschreiben. Klare Fakten sind hier sehr viel besser geeignet um die helfen zu können.

    Also bspw. so:

    [Tabelle Ausgaben]
    ID   int   Primärschlüssel
    Datum   date
    Betrag   float

    Alternativ auch das CREATE TABLE Statement dazu, bei größeren Tabellen ist das ggfs. besser.

    [SQL Statement]

    CREATE TABLE [dbo].[Ausgaben](
    	[ID] [int] IDENTITY(1,1) NOT NULL,
    	[Datum] [date] NOT NULL,
    	[Betrag] [float] NULL,
     CONSTRAINT [PK_Ausgaben] PRIMARY KEY CLUSTERED 
    (
    	[ID] ASC
    )
    ) ON [PRIMARY]

    [Beispieldaten]


    ID   Datum         Betrag
    1    2013-02-01    20
    2    2013-02-01    30
    3    2013-02-01    20
    4    2013-03-01    10
    5    2013-03-01    15

    [Gewünschtes Ergebnis]

    2013-02-01    70
    2013-03-01    25

    In dem Fall würde das benötigte SQL Statement bspw. so aussehen:

    SELECT   Datum,
             SUM( Betrag ) AS SummeAusgaben
    FROM     Ausgaben
    GROUP BY Datum


    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




    Freitag, 1. März 2013 18:22
    Moderator
  • Hallo Webdesigner,

    aus Deinem Coding geht hervor, dass u. a. die Relation selbst eine Variable sein soll. Dies geht in Funktionen nicht:
    http://msdn.microsoft.com/de-de/library/ms186755.aspx

    Sofern Du tatsächlich die Relation selbst als Variable übergeben möchtest, kannst Du das nur durch zwei Lösungsansätze erreichen:

    • Verwendung einer Stored Procedure
    • Verwendung einer CLR-Function

    Die Verwendung einer CLR-Funktion halte ich in Hochverfügbarkeitsumgebungen für fragwürdig - Gleiches gilt für Sicherheitsumgebungen (Banken, Versicherungen, ...)

    Die Verwendung einer Stored Procedure wird in diesem Fall die einzige Lösung sein. Hierzu hat Frank aber schon mit einem Link auf die Sicherheitsrisiken (SQL Injection) hingewiesen. Sofern Du dieses Risiko tragen möchtest, kann man das wie folgt lösen:

    USE tempdb
    GO
    -- Erstellen zweier Tabellen für die unterschiedlche Verwendung
    IF OBJECT_ID('dbo.firsttable', 'U') IS NOT NULL
    	DROP TABLE dbo.firsttable
    	GO
    IF OBJECT_ID('dbo.secondtable', 'U') IS NOT NULL
    	DROP TABLE dbo.secondtable
    	GO
    CREATE TABLE dbo.firsttable
    (
    	id	int	not null	identity (1, 1) PRIMARY KEY CLUSTERED,
    	col1	char(20)	NOT NULL	DEFAULT ('just a column'),
    	col2	char(30)	NOT NULL	DEFAULT ('just a second column')
    );
    CREATE TABLE dbo.secondtable
    (
    	id	int	not null	identity (1, 1) PRIMARY KEY CLUSTERED,
    	col1	int	NOT NULL	DEFAULT (rand() * 10000),
    	col2	int	NOT NULL	DEFAULT (rand() * 1000),
    	col3	AS col1 * col2
    );
    -- Befüllen der Tabellen mit ein paar Daten
    SET NOCOUNT ON
    GO
    INSERT INTO dbo.firsttable DEFAULT VALUES
    GO 100
    INSERT INTO dbo.secondtable DEFAULT VALUES
    GO 100
    --SELECT * FROM dbo.firsttable;
    --SELECT * FROM dbo.secondtable;
    GO
    -- Erstellen einer Stored Procedure für die Anforderungen
    IF OBJECT_ID('dbo.myproc', 'P') IS NOT NULL
    	DROP PROC dbo.myproc
    	GO
    CREATE PROC dbo.myproc
    	@table_name	sysname
    AS
    	SET NOCOUNT ON
    	
    	-- Sollte die Relation nicht vorhanden sein, Fehler!
    	IF OBJECT_ID(@table_name) IS NULL
    	BEGIN
    		RAISERROR ('Eine Tabelle %s existiert nicht', 0, 1, @table_name) WITH NOWAIT
    		RETURN
    	END
    	
    	DECLARE	@stmt	nvarchar(4000)
    	SET		@stmt	=	'SELECT * FROM ' + @table_name + ';'
    	EXEC	sp_executeSQL @stmt;
    	SET NOCOUNT OFF
    GO
    -- Test
    EXEC dbo.myproc 'dbo.firsttable'

    Der Code ist relativ trivial - zunächst werden zwei Tabellen erstellt, die mit jeweils 100 Testdaten gefüllt werden. Anschließend erstelle ich eine Prozedur, die mittels sp_executeSQL einen SELECT auf die - als Parameter - übergebene Tabelle übergibt.

    Bezüglich der von DIr geforderten "Berechnung" schau' Dir bitte mal die Tabelle dbo.secondtable an - in ihr ist das dritte Attribut eine Berechnung aus col1 und col2. Sofern Du nach berechneten Werten suchst, muß die Berechnung PERSISTED sein, um dieses Attribut mit einem Index versehen zu können.

    Problem einer Prozedur in Gegensatz zu einer Funktion... - sie kann nicht in einem SELECT-Konstrukt verwendet werden!

    Da jedoch nicht genau klar ist, was Du eigentlich machen möchtest, mußt Du schon etwas mehr Informationen bereitstellen.

    Weitere Information zu den von mir angesprochenen Themen:

    sp_executeSQL: http://msdn.microsoft.com/de-de/library/ms188001.aspx
    persisted columns: http://msdn.microsoft.com/de-de/library/ms186241.aspx


    Uwe Ricken

    MCSE - SQL Server 2012
    MCSA - SQL Server 2012
    MCITP Database Administrator 2005
    MCITP Database Administrator 2008
    MCITP Microsoft SQL Server 2008, Database Development

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

    Montag, 4. März 2013 06:33