Sunday, January 9, 2011

SQL Functions

SQL has many built-in functions for performing calculations on data.

SQL Aggregate Functions

SQL aggregate functions return a single value, calculated from values in a column.
Useful aggregate functions:
  • AVG() - Returns the average value
  • COUNT() - Returns the number of rows
  • FIRST() - Returns the first value
  • LAST() - Returns the last value
  • MAX() - Returns the largest value
  • MIN() - Returns the smallest value
  • SUM() - Returns the sum

SQL Scalar functions

SQL scalar functions return a single value, based on the input value.
Useful scalar functions:
  • UCASE() - Converts a field to upper case
  • LCASE() - Converts a field to lower case
  • MID() - Extract characters from a text field
  • LEN() - Returns the length of a text field
  • ROUND() - Rounds a numeric field to the number of decimals specified
  • NOW() - Returns the current system date and time
  • FORMAT() - Formats how a field is to be displayed

Creates a user-defined function in SQL Server 2008 R2. A user-defined function is a Transact-SQL or common language runtime (CLR) routine that accepts parameters, performs an action, such as a complex calculation, and returns the result of that action as a value. The return value can either be a scalar (single) value or a table. Use this statement to create a reusable routine that can be used in these ways:

  • In Transact-SQL statements such as SELECT
  • In applications calling the function
  • In the definition of another user-defined function
  • To parameterize a view or improve the functionality of an indexed view
  • To define a column in a table
  • To define a CHECK constraint on a column
  • To replace a stored procedure


    --Transact-SQL Scalar Function Syntax
    CREATE FUNCTION [ schema_name. ] function_name 
    ( [ { @parameter_name [ AS ][ type_schema_name. ] parameter_data_type 
        [ = default ] [ READONLY ] } 
        [ ,...n ]
      ]
    )
    RETURNS return_data_type
        [ WITH <function_option> [ ,...n ] ]
        [ AS ]
        BEGIN 
            function_body 
            RETURN scalar_expression
        END
    [ ; ]
    --Transact-SQL Multistatement Table-valued Function Syntax
    CREATE FUNCTION [ schema_name. ] function_name 
    ( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type 
        [ = default ] [READONLY] } 
        [ ,...n ]
      ]
    )
    RETURNS @return_variable TABLE <table_type_definition>
        [ WITH <function_option> [ ,...n ] ]
        [ AS ]
        BEGIN 
            function_body 
            RETURN
        END
    [ ; ]
    
    --Transact-SQL Function Clauses 
    <function_option>::= 
    {
        [ ENCRYPTION ]
      | [ SCHEMABINDING ]
      | [ RETURNS NULL ON NULL INPUT | CALLED ON NULL INPUT ]
      | [ EXECUTE_AS_Clause ]
    }
    
    <table_type_definition>:: = 
    ( { <column_definition> <column_constraint> 
      | <computed_column_definition> } 
        [ <table_constraint> ] [ ,...n ]
    ) 
    <column_definition>::=
    {
        { column_name data_type }
        [ [ DEFAULT constant_expression ] 
          [ COLLATE collation_name ] | [ ROWGUIDCOL ]
        ]
        | [ IDENTITY [ (seed , increment ) ] ]
        [ <column_constraint> [ ...n ] ] 
    }
    
    <column_constraint>::= 
    {
        [ NULL | NOT NULL ] 
        { PRIMARY KEY | UNIQUE }
          [ CLUSTERED | NONCLUSTERED ] 
          [ WITH FILLFACTOR = fillfactor 
            | WITH ( < index_option > [ , ...n ] )
          [ ON { filegroup | "default" } ]
      | [ CHECK ( logical_expression ) ] [ ,...n ]
    }
    
    <computed_column_definition>::=
    column_name AS computed_column_expression 
    
    <table_constraint>::=
    { 
        { PRIMARY KEY | UNIQUE }
          [ CLUSTERED | NONCLUSTERED ] 
          ( column_name [ ASC | DESC ] [ ,...n ] )
            [ WITH FILLFACTOR = fillfactor 
            | WITH ( <index_option> [ , ...n ] )
      | [ CHECK ( logical_expression ) ] [ ,...n ]
    }
    
    <index_option>::=
    { 
        PAD_INDEX = { ON | OFF } 
      | FILLFACTOR = fillfactor 
      | IGNORE_DUP_KEY = { ON | OFF }
      | STATISTICS_NORECOMPUTE = { ON | OFF } 
      | ALLOW_ROW_LOCKS = { ON | OFF }
      | ALLOW_PAGE_LOCKS ={ ON | OFF } 
    }
    --CLR Scalar Function Syntax
    CREATE FUNCTION [ schema_name. ] function_name 
    ( { @parameter_name [AS] [ type_schema_name. ] parameter_data_type 
        [ = default ] } 
        [ ,...n ]
    )
    RETURNS { return_data_type }
        [ WITH <clr_function_option> [ ,...n ] ]
        [ AS ] EXTERNAL NAME <method_specifier>
    [ ; ]
    --CLR Table-Valued Function Syntax
    CREATE FUNCTION [ schema_name. ] function_name 
    ( { @parameter_name [AS] [ type_schema_name. ] parameter_data_type 
        [ = default ] } 
        [ ,...n ]
    )
    RETURNS TABLE <clr_table_type_definition> 
        [ WITH <clr_function_option> [ ,...n ] ]
        [ ORDER ( <order_clause> ) ]
        [ AS ] EXTERNAL NAME <method_specifier>
    [ ; ]
    --CLR Function Clauses
    <order_clause> ::= 
    {
       <column_name_in_clr_table_type_definition>
       [ ASC | DESC ] 
    } [ ,...n] 
    
    <method_specifier>::=
        assembly_name.class_name.method_name
    
    <clr_function_option>::=
    }
        [ RETURNS NULL ON NULL INPUT | CALLED ON NULL INPUT ]
      | [ EXECUTE_AS_Clause ]
    }
    
    <clr_table_type_definition>::= 
    ( { column_name data_type } [ ,...n ] )
    
    USE AdventureWorks2008R2;
    GO
    IF OBJECT_ID (N'dbo.ISOweek', N'FN') IS NOT NULL
        DROP FUNCTION dbo.ISOweek;
    GO
    CREATE FUNCTION dbo.ISOweek (@DATE datetime)
    RETURNS int
    WITH EXECUTE AS CALLER
    AS
    BEGIN
         DECLARE @ISOweek int;
         SET @ISOweek= DATEPART(wk,@DATE)+1
              -DATEPART(wk,CAST(DATEPART(yy,@DATE) as CHAR(4))+'0104');
    --Special cases: Jan 1-3 may belong to the previous year
         IF (@ISOweek=0) 
              SET @ISOweek=dbo.ISOweek(CAST(DATEPART(yy,@DATE)-1 
                   AS CHAR(4))+'12'+ CAST(24+DATEPART(DAY,@DATE) AS CHAR(2)))+1;
    --Special case: Dec 29-31 may belong to the next year
         IF ((DATEPART(mm,@DATE)=12) AND 
              ((DATEPART(dd,@DATE)-DATEPART(dw,@DATE))>= 28))
              SET @ISOweek=1;
         RETURN(@ISOweek);
    END;
    GO
    SET DATEFIRST 1;
    SELECT dbo.ISOweek(CONVERT(DATETIME,'12/26/2004',101)) AS 'ISO Week';
    Here is the result set.
    ISO Week
    ----------------
    52
    
    
    
    
    
    
    USE AdventureWorks2008R2;
    GO
    IF OBJECT_ID (N'Sales.ufn_SalesByStore', N'IF') IS NOT NULL
        DROP FUNCTION Sales.ufn_SalesByStore;
    GO
    CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
    RETURNS TABLE
    AS
    RETURN 
    (
        SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS 'Total'
        FROM Production.Product AS P 
        JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID
        JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID
        JOIN Sales.Customer AS C ON SH.CustomerID = C.CustomerID
        WHERE C.StoreID = @storeid
        GROUP BY P.ProductID, P.Name
    );
    GO
    To invoke the function, run this query.
    SELECT * FROM Sales.ufn_SalesByStore (602);

     User-Defined Function

    CREATE FUNCTION whichContinent 
    (@Country nvarchar(15))
    RETURNS varchar(30)
    AS
    BEGIN
    declare @Return varchar(30)
    select @return = case @Country
    when 'Argentina' then 'South America'
    when 'Belgium' then 'Europe'
    when 'Brazil' then 'South America'
    when 'Canada' then 'North America'
    when 'Denmark' then 'Europe'
    when 'Finland' then 'Europe'
    when 'France' then 'Europe'
    else 'Unknown'
    end
    
    return @return
    end
    print dbo.WhichContinent('USA')
    
    select dbo.WhichContinent(Customers.Country), customers.* 
    from customers
    
    create table test
    (Country varchar(15),
    Continent as (dbo.WhichContinent(Country)))
    
    insert into test (country) 
    values ('USA')
    
    select * from test
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    
    Country          Continent
    ---------------  ------------------------------
    USA              North America

Multi-statement Table-Value User-Defined Function

CREATE FUNCTION dbo.customersbycountry ( @Country varchar(15) )
RETURNS 
 @CustomersbyCountryTab table (
  [CustomerID] [nchar] (5), [CompanyName] [nvarchar] (40), 
  [ContactName] [nvarchar] (30), [ContactTitle] [nvarchar] (30), 
  [Address] [nvarchar] (60), [City] [nvarchar] (15),
  [PostalCode] [nvarchar] (10), [Country] [nvarchar] (15), 
  [Phone] [nvarchar] (24), [Fax] [nvarchar] (24)
 )
AS
BEGIN
 INSERT INTO @CustomersByCountryTab 
 SELECT  [CustomerID], 
   [CompanyName], 
   [ContactName], 
   [ContactTitle], 
   [Address], 
   [City], 
   [PostalCode], 
   [Country], 
   [Phone], 
   [Fax] 
 FROM [Northwind].[dbo].[Customers]
 WHERE country = @Country
 
 DECLARE @cnt INT
 SELECT @cnt = COUNT(*) FROM @customersbyCountryTab
 
 IF @cnt = 0
  INSERT INTO @CustomersByCountryTab (
   [CustomerID],
   [CompanyName],
   [ContactName],
   [ContactTitle],
   [Address],
   [City],
   [PostalCode],
   [Country], 
   [Phone],
   [Fax]  )
  VALUES ('','No Companies Found','','','','','','','','')
 
 RETURN
END
GO
SELECT * FROM dbo.customersbycountry('USA')
SELECT * FROM dbo.customersbycountry('CANADA')
SELECT * FROM dbo.customersbycountry('ADF')

No comments :

Post a Comment