/* Procedury Skadowane */

/* Tworzenie procedury skadowanej: podstawy skadni */

USE Northwind
GO
CREATE PROC spShippers
AS
   SELECT * FROM Shippers

EXEC spShippers

/* Okrelanie parametrw */

USE Northwind
GO
CREATE PROC spInsertShipper
   @CompanyName   nvarchar(40),
   @Phone         nvarchar(24)
AS
   INSERT INTO Shippers
   VALUES
      (@CompanyName, @Phone)


EXEC spInsertShipper 'Speedy Shippers, Inc.', '(503) 555-5566'

EXEC spShippers

EXEC spInsertShipper 'Speedy Shippers, Inc.' --Przykad bdny

/* Okrelanie wartoci domylnych */

USE Northwind
GO

CREATE PROC spInsertShipperOptionalPhone
   @CompanyName   nvarchar(40),
   @Phone         nvarchar(24) = NULL
AS
   INSERT INTO Shippers
   VALUES
      (@CompanyName, @Phone)

EXEC spInsertShipperOptionalPhone 'Speedy Shippers, Inc.'

EXEC spShippers

/* Tworzenie parametrw wyjciowych */

USE Northwind
GO
CREATE PROC spInsertOrder
   @CustomerID     nvarchar(5),
   @EmployeeID     int,
   @OrderDate      datetime     = NULL,
   @RequiredDate   datetime     = NULL,
   @ShippedDate    datetime     = NULL,
   @ShipVia        int,
   @Freight        money,
   @ShipName       nvarchar(40) = NULL,
   @ShipAddress    nvarchar(60) = NULL,
   @ShipCity       nvarchar(15) = NULL,
   @ShipRegion     nvarchar(15) = NULL,
   @ShipPostalCode nvarchar(10) = NULL,
   @ShipCountry    nvarchar(15) = NULL,
   @OrderID        int       OUTPUT

AS
   /*Dodaj nowy rekord*/
   INSERT INTO Orders
   VALUES
      (
         @CustomerID,
         @EmployeeID,
         @OrderDate,
         @RequiredDate,
         @ShippedDate,
         @ShipVia,
         @Freight,
         @ShipName,
         @ShipAddress,
         @ShipCity,
         @ShipRegion,
         @ShipPostalCode,
         @ShipCountry
      )
/* Zapisz identyfikatory nowych rekordw do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY


USE Northwind
GO
DECLARE   @MyIdent int
EXEC   spInsertOrder
   @CustomerID = 'ALFKI',
   @EmployeeID = 5,
   @OrderDate = '5/1/1999',
   @ShipVia = 3,
   @Freight = 5.00,
   @OrderID = @MyIdent OUTPUT
SELECT @MyIdent AS IdentityValue
SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
FROM Orders
WHERE OrderID = @MyIdent

/* Instrukcje sterujce przepywem danych */

USE Northwind
GO
CREATE PROC spInsertDateValidatedOrder
   @CustomerID      nvarchar(5),
   @EmployeeID      int,
   @OrderDate       datetime      = NULL,
   @RequiredDate    datetime      = NULL,
   @ShippedDate     datetime      = NULL,
   @ShipVia        int,
   @Freight        money,
   @ShipName        nvarchar(40)   = NULL,
   @ShipAddress     nvarchar(60)   = NULL,
   @ShipCity        nvarchar(15)   = NULL,
   @ShipRegion      nvarchar(15)   = NULL,
   @ShipPostalCode  nvarchar(10)   = NULL,
   @ShipCountry     nvarchar(15)   = NULL,
   @OrderID         int   OUTPUT
AS
/* Sprawd, czy podana data jest starsza ni 7 dni, jeli tak,  zastp j wartoci NULL */
IF DATEDIFF(dd, @OrderDate, GETDATE()) > 7
   SELECT @OrderDate = NULL

/* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
   @OrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY


USE Northwind
GO
DECLARE   @MyIdent   int
EXEC spInsertDateValidatedOrder
   @CustomerID = 'ALFKI',
   @EmployeeID = 5,
   @OrderDate = '5/1/1999',
   @ShipVia = 3,
   @Freight = 5.00,
   @OrderID = @MyIdent   OUTPUT
SELECT @MyIdent AS IdentityValue
SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
FROM Orders
WHERE OrderID = @MyIdent


USE Northwind
GO
SELECT TOP 5 OrderID, OrderDate
FROM Orders
WHERE OrderDate IS NOT NULL
ORDER BY OrderDate


USE Northwind
GO
DECLARE   @MyIdent   int
DECLARE   @MyDate   smalldatetime
SELECT   @MyDate = GETDATE()
EXEC spInsertDateValidatedOrder
   @CustomerID   = 'ALFKI',
   @EmployeeID   = 5,
   @OrderDate = @MyDate,
   @ShipVia   = 3,
   @Freight = 5.00,
   @OrderID = @MyIdent OUTPUT
SELECT @MyIdent AS IdentityValue
SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
FROM Orders
WHERE OrderID = @MyIdent


SELECT CONVERT(datetime, (CONVERT(varchar,GETDATE(),112)))


/* Implementacja instrukcji ELSE w procedurze skadowanej */


USE Northwind
GO
ALTER PROC spInsertDateValidatedOrder
   @CustomerID   nvarchar(5),
   @EmployeeID      int,
   @OrderDate       datetime       = NULL,
   @RequiredDate    datetime       = NULL,
   @ShippedDate     datetime       = NULL,
   @ShipVia         int,
   @Freight         money,
   @ShipName        nvarchar(40)   = NULL,
   @ShipAddress     nvarchar(60)   = NULL,
   @ShipCity        nvarchar(15)   = NULL,  
   @ShipRegion      nvarchar(15)   = NULL,
   @ShipPostalCode  nvarchar(10)   = NULL,
   @ShipCountry     nvarchar(15)   = NULL,
   @OrderID         int      OUTPUT   
   
AS

/* Nie lubi zmienia parametrw wejciowych - okazuj si one przydatne w czasie debugowania, kiedy moesz  odwoywa si do ich pierwotnych wartoci. Z tego powodu zadeklarujemy osobn zmienn, do ktrej przypiszemy warto kocow, ktr wstawimy do tabeli. */
DECLARE   @InsertedOrderDate      smalldatetime
/* Sprawd, czy podana data jest starsza ni 7 dni, jeli tak zastp j wartoci NULL, w przeciwnym wypadku przytnij czas ustawiajc pnoc */
IF DATEDIFF(dd, @OrderDate, GETDATE()) > 7
   SELECT @InsertedOrderDate = NULL
ELSE
   SELECT @InsertedOrderDate = 
   CONVERT(datetime, (CONVERT(varchar,@OrderDate,112)))
   /* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
   @InsertedOrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY


/* Grupowanie kodu w bloki */

USE Northwind
GO
ALTER PROC spInsertDateValidatedOrder
   @CustomerID     nvarchar(5),
   @EmployeeID     int,
   @OrderDate      datetime   = NULL,
   @RequiredDate   datetime   = NULL,
   @ShippedDate    datetime   = NULL,
   @ShipVia        int,
   @Freight        money,
   @ShipName       nvarchar(40)   = NULL,
   @ShipAddress    nvarchar(60)   = NULL,
   @ShipCity       nvarchar(15)   = NULL,
   @ShipRegion     nvarchar(15)   = NULL,
   @ShipPostalCode nvarchar(10)   = NULL,
   @ShipCountry    nvarchar(15)   = NULL,
   @OrderID        int   OUTPUT
AS
   /* Nie lubi zmienia parametrw wejciowych - okazuj si one przydatne w czasie debugowania, kiedy moesz  odwoywa si do ich pierwotnych wartoci. Z tego powodu zadeklarujemy  osobn zmienn, do ktrej przypiszemy warto kocow, ktr wstawimy do tabeli.*/
DECLARE   @InsertedOrderDate   smalldatetime

/* Sprawd, czy podana data jest starsza ni 7 dni, jeli tak, zastp j wartoci NULL, w przeciwnym wypadku przytnij czas ustawiajc pnoc */
IF DATEDIFF (dd, @OrderDate, GETDATE()) > 7
BEGIN
   SELECT @InsertedOrderDate = NULL
   PRINT 'Invalid Order Date'
   PRINT 'Supplied Order Date was greater than 7 days old.'
   PRINT 'The value has been reset to NULL'
END
ELSE
BEGIN
   SELECT @InsertedOrderDate = 
      CONVERT(datetime, (CONVERT(varchar, @OrderDate, 112)))
      PRINT 'The Time of Day in Order Date was truncated'
END
/* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
	 @InsertedOrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY



USE Northwind
GO
DECLARE   @MyIdent   int
DECLARE   @MyDate   smalldatetime
SELECT @MyDate = GETDATE()
EXEC spInsertDateValidatedOrder
   @CustomerID = 'ALFKI',
   @EmployeeID = 5,
   @OrderDate @MyDate,
   @ShipVia = 3,
   @Freight = 5.00,
   @OrderID = @MyIdent OUTPUT
SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
FROM Orders
WHERE OrderID = @MyIdent


USE Northwind
GO
DECLARE   @MyIdent      int
EXEC spInsertDateValidatedOrder
   @CustomerID = 'ALFKI',
   @EmployeeID = 5,
   @OrderDate = '1/1/1999',
   @ShipVia = 3,
   @Freight = 5.00,
   @OrderID = @MyIdent OUTPUT
SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
FROM Orders
WHERE OrderID = @MyIdent


/* Instrukcja CASE */


USE Northwind
GO
SELECT TOP 10 OrderID, OrderID % 10 AS 'Last Digit', Position =
CASE OrderID % 10
   WHEN 1 THEN 'First'
   WHEN 2 THEN 'Second'
   WHEN 3 THEN 'Third'
   WHEN 4 THEN 'Fourth'
   ELSE 'Something Else'
END
FROM Orders


USE Northwind
GO
SELECT TOP 10 OrderID % 10 AS "Last Digit",
   ProductID,
   "How Close?" = CASE OrderID % 10
      WHEN ProductID THEN 'Exact Match!'
      WHEN ProductID - 1 THEN 'Whitin 1'
      WHEN ProductID + 1 THEN 'Whitin 1'
      ELSE 'More Than One Apart'
   END
FROM [Order Details]
WHERE ProductID < 10
ORDER BY OrderID DESC


USE Northwind
GO
SELECT TOP 10 OrderID % 10 AS "Last Digit",
   ProductID,
   "How Close?" = CASE
      WHEN (OrderID % 10) < 3 THEN 'Ends With Less Than Three'
      WHEN ProductID = 6 THEN 'ProductID is 6'
      WHEN ABS(OrderID % 10 - ProductID) <= 1 THEN 'Within 1'
      ELSE 'More Than One Apart'
   END
FROM [Order Details]
WHERE ProductID < 10
ORDER BY OrderID DESC


USE Northwind
GO
/* Uyjemy dodatkowej zmiennej, jeeli zajdzie potrzeba zmiany wartoci przy nastpnym uruchomieniu zapytania, zmienimy tylko ten jeden punkt */
DECLARE @Markup     money 
DECLARE @Multiplier money

SELECT @Markup = .10               -- Tutaj zmie warto wzrostu
SELECT @Multiplier = @Markup + 1   -- Chcemy uzyska cen kocow, a nie 
					    -- wielko wzrostu, wic dodajemy 1   
/* Dokonajmy zmian. Zauwa, e ograniczamy liczb pozycji do 10. W rzeczywistoci nie bdziemy tego robi, ewentualnie zastosujemy bardziej zoon klauzul WHERE w celu ograniczenia liczby produktw, ktrych dotyczy wzrost */
SELECT TOP 10 ProductID, ProductName, UnitPrice,
   UnitPrice * @Multiplier AS "Marked Up Price", "New Price" =
   CASE WHEN FLOOR(UnitPrice * @Multiplier + .24)
             > FLOOR(UnitPrice * @Multiplier)
                THEN FLOOR(UnitPrice * @Multiplier) + .95
          WHEN FLOOR(UnitPrice * @Multiplier + .5) >
               FLOOR(UnitPrice * @Multiplier)
                     THEN FLOOR(UnitPrice * @Multiplier) + .75
          ELSE FLOOR(UnitPrice * @Multiplier) + .49
   END
FROM Products
ORDER BY ProductID DESC   -- Poniewa sortowanie w d wydaje si tu bardziej pasowa



USE Northwind
GO
CREATE PROC spMarkupTest
   @MarkupAsPercent   money
AS
   DECLARE @Multiplier money
-- Chcemy uzyska cen kocow a nie wielko wzrostu
SELECT @Multiplier = @MarkupAsPercent / 100 + 1 /*of the increase, so add 1*/
/* Dokonajmy zmian. Zauwa, e ograniczamy liczb pozycji do 10. W rzeczywistoci nie bdziemy tego robi, ewentualnie zastosujemy bardziej zoon klauzul WHERE w celu ograniczenia liczby produktw, ktrych dotyczy wzrost */
SELECT TOP 10 ProductID, ProductName, UnitPrice,
   UnitPrice * @Multiplier AS "Marked Up Price", "New Price" =
   CASE WHEN FLOOR(UnitPrice * @Multiplier + .24)
               > FLOOR(UnitPrice * @Multiplier)
                       THEN FLOOR(UnitPrice * @Multiplier) + .95
        WHEN FLOOR(UnitPrice  * @Multiplier + .5) >
              FLOOR(UnitPrice * @Multiplier)
                       THEN FLOOR(UnitPrice * @Multiplier) + .75
        ELSE FLOOR(UnitPrice * @Multiplier) + .49
   END
FROM Products
ORDER BY ProductID DESC   -- Poniewa sortowanie w d wydaje si tu bardziej pasowa


EXEC spMarkupTest 10


/* Zaptlanie przy uyciu instrukcji WHILE */


WHILE 1 = 1
BEGIN
   WAITFOR TIME '01:00'
   EXEC sp_updatestats
   RAISERROR('Statistics Updated for Database', 1, 1) WITH LOG
END


/* Instrukcja WAITFOR */


WAITFOR DELAY '01:00'

WAITFOR TIME '01:00'


/* Jak uywa RETURN */


USE Northwind
GO
CREATE PROC spTestReturns
AS
   DECLARE @MyMessage    varchar (50)
   DECLARE @MyOtherMessage    varchar(50)
SELECT @MyMessage = 'Hi, it''s that line before the RETURN'
PRINT @MyMessage
RETURN
SELECT @MyOtherMessage = 'Sorry, but we won''t get this far'
PRINT @MyOtherMessage
RETURN 


EXEC @ReturnVal = spMySproc


DECLARE @Return int
EXEC @Return = spTestReturns
SELECT @Return


USE Northwind
GO
ALTER PROC spTestReturns
AS
   DECLARE @MyMessage      varchar(50)
   DECLARE @MyOtherMessage   varchar(50)
   SELECT @MyMessage = 'Hi, it''s that line before the RETURN'
   PRINT @MyMessage
   RETURN 100
   SELECT @MyOtherMessage = 'Sorry, but we won''t get this far'
   PRINT @MyOtherMessage
RETURN



/* Obsuga bdu */


USE Northwind  --Przykad bdny
GO
INSERT INTO [Order Details]
   (OrderID, ProductID, UnitPrice, Quantity, Discount)
VALUES
   (999999,11,10.00,10, 0)


/* Wykorzystanie @@ERROR */


USE Northwind
GO
DECLARE   @Error      int
-- Bdny INSERT  nie wystpuje OrderID 999999 w bazie Northwind
INSERT INTO [Order Details]
   (OrderID, ProductID, UnitPrice,Quantity, Discount)
VALUES
   (999999,11,10.00,10, 0)
-- Przenie kod bdu w bezpieczne miejsce. Zwr uwag, e po wykonaniu tej instrukcji @@Error bdzie zawiera numer bdu tej instrukcji
SELECT @Error = @@ERROR
-- Wywietl pust lini
PRINT ''
-- Wylwietl numer bdu przechowywany w zmiennej
PRINT 'The Value of @Error is ' + CONVERT(varchar, @Error)
-- Warto @@Error zostaa zresetowana - wynosi zero
PRINT 'The Value of @@ERROR is ' + CONVERT(varchar, @@ERROR)


/* Wykorzstanie @@ERROR w procedurze skadowanej */


USE Northwind --Przykad bdny
GO
DECLARE   @MyIdent   int
DECLARE   @MyDate            smalldatetime
SELECT @MyDate = GETDATE()
EXEC spInsertDateValidatedOrder
   @CustomerID  = 'ZXZXZ',
   @EmployeeID  = 5,
   @OrderDate   = @MyDate,
   @ShipVia     = 3,
   @Freight     = 5.00,
   @OrderID     = @MyIdent OUTPUT
   
SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
FROM Orders   
WHERE OrderID = @MyIdent



USE Northwind
GO
ALTER PROC spInsertDateValidatedOrder
   @CustomerID     nvarchar(5),
   @EmployeeID     int,   
   @OrderDate      datetime     = NULL,
   @RequiredDate   datetime     = NULL,
   @ShippedDate    datetime     = NULL,
   @ShipVia        int,
   @Freight        money,
   @ShipName       nvarchar(40) = NULL,
   @ShipAddress    nvarchar(60) = NULL,
   @ShipCity       nvarchar(15) = NULL,
   @ShipRegion     nvarchar(15) = NULL,
   @ShipPostalCode nvarchar(10) = NULL,
   @ShipCountry    nvarchar(15) = NULL,
   @OrderID        int       OUTPUT

AS
-- Deklaracje zmiennych
DECLARE   @Error         int
DECLARE   @InsertedOrderDate   smalldatetime
/* Sprawd, czy podana data jest starsza ni 7 dni, jeli tak, zastp j wartoci NULL, w przeciwnym wypadku przytnij czas ustawiajc pnoc */
IF DATEDIFF(dd, @OrderDate, GETDATE()) > 7
BEGIN
   SELECT @InsertedOrderDate = NULL
   PRINT 'Invalid Order Date'
   PRINT 'Supplied OrderDate was greater than 7 days old.'
   PRINT 'The value has been reset to NULL'
END
ELSE
BEGIN
   SELECT @InsertedOrderDate =
      CONVERT(datetime, (CONVERT(varchar, @OrderDate, 112)))
      PRINT 'The Time of Day in Order Date was truncated'
END
/* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
   @InsertedOrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)
-- Przypisz warto bdu do zmiennej lokalnej i sprawd warunek bdu
SELECT @Error = @@ERROR
IF @Error != 0
BEGIN
   -- O nie! Co poszo le.
   IF @Error = 547
   -- Bd naruszenia ograniczenia. Wypisz informacje o moliwych rozwizaniach 
   --problemu.
   BEGIN
      PRINT 'Supplied data violates data integrity rules'
      PRINT 'Check that the supplied customer number exists'
      PRINT 'in the system and try again'
   END
   ELSE
   -- Zdarzyo si co nieprzewidzianego, wywietl informacje o nieznanym bdzie.
   BEGIN
      PRINT 'An unknown error occured. Contact your System Administrator'
      PRINT 'The error was number ' + CONVERT(varchar, @Error)
   END
   -- Pomimo wystpienia bdu, przelij fragment kodu do punktu wywoania w celu 
   --poprawienia go z jego poziomu.
   RETURN @Error
END
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY
RETURN


USE Northwind
GO
DECLARE   @MyIdent   int
DECLARE   @MyDate         smalldatetime
DECLARE   @Return    int
SELECT @MyDate = GETDATE()
EXEC @Return = spInsertDateValidatedOrder
   @CustomerID = 'ZXZXZ',
   @EmployeeID = 5,
   @OrderDate  = @MyDate,
   @ShipVia    = 3,
   @Freight    = 5.00,
   @OrderID    = @MyIdent OUTPUT
IF @Return = 0
   SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
   FROM Orders
   WHERE OrderID = @MyIdent
ELSE
   PRINT 'Value Retirned was ' + CONVERT(varchar, @Return)

/*****************************************************/    


ELSE
BEGIN
   SELECT @InsertedOrderDate =
      CONVERT(datetime, (CONVERT(varchar, @OrderDate, 112)))
      PRINT 'The Time of Day in Order Date was truncated'
END

/* Ustanowienie bloku TRY/CATCH */
BEGIN TRY

/* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
   @InsertedOrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)

END TRY
BEGIN CATCH
   -- O nie! Co poszo le. Sprawdmy, czy moemy co z tym zrobi. 
   DECLARE @ErrorNo   int,
         @Severity   tinyint,
         @State      smallint,
         @LineNo      int,
         @Message   nvarchar(4000)
   SELECT 
        @ErrorNo = ERROR_NUMBER(),
        @Severity = ERROR_SEVERITY(),
        @State = ERROR_STATE(),
        @LineNo = ERROR_LINE (),
        @Message = ERROR_MESSAGE()
   IF @ErrorNo = 547
   -- Bd naruszenia ograniczenia. Wypisz informacje o moliwych rozwizaniach 
   --problemu.
   BEGIN
      PRINT 'Supplied data violates data integrity rules'
      PRINT 'Check that the supplied customer number exists'
      PRINT 'in the system and try again'
   END
   ELSE
   -- Zdarzyo si co nieprzewidzianego, wywietl informacje o nieznanym bdzie.
   BEGIN
      PRINT 'An unknown error occured. Contact your System Administrator'
      PRINT 'The error was number ' + CONVERT(varchar, @Error)
   END
   -- Pomimo wystpienia bdu, przelij fragment kodu do punktu wywoania w celu 
   --obsuenia go z jego poziomu.
   RETURN @Error
END CATCH
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY
RETURN


/* Obsuga bdw przed ich wystpieniem */


USE Northwind
GO
ALTER PROC spInsertDateValidatedOrder
   @CustomerID       nvarchar(5),
   @EmployeeID       int,
   @OrderDate        datetime     = NULL,
   @RequiredDate     datetime     = NULL,
   @ShippedDate      datetime     = NULL,
   @ShipVia	     int,
   @Freight	     money,
   @ShipName         nvarchar(40) = NULL,
   @ShipAddress      nvarchar(60) = NULL,
   @ShipCity         nvarchar(15) = NULL,
   @ShipRegion       nvarchar(15) = NULL,
   @ShipPostalCode   nvarchar(10) = NULL,
   @ShipCountry      nvarchar(15) = NULL,
   @OrderID          int      OUTPUT
AS
-- Deklaracje zmiennych
DECLARE   @Error               int
DECLARE   @InsertedOrderDate   smalldatetime
/* Tutaj deklarujemy stae. W SQL Server nie wystpuje pojcie staej w klasycznym znaczeniu, wic stosuj standardow zmienn w ich miejsce. Pozwala to utrzyma bardziej czytelny kod - zwaszcza, gdy zostan umieszczone na licie staych w programie klienckim. */
DECLARE   @INVALIDDATE   int
/* Po zadeklarowaniu staych inicjalizujemy je. Zauwa, e SQL Server ignoruje biae spacje pomidzy zmienn i znakiem "=". Umieszczenie spacji byoby bardziej oczywiste w sytuacji, gdyby staych byo wicej - ich wartoci zostayby wyrwnane dla zwikszenia czytelnoci. */
SELECT   @INVALIDDATE = -1000
/* Sprawd, czy podana data jest starsza ni 7 dni, jeli tak, nie jest duej prawidowa. Sprawd te wystpowanie wartoci NULL. Jeli ktry z warunkw jest prawdziwy, zakocz dziaanie procedury skadowanej wywietlajc informacje o bdzie. */
IF DATEDIFF(dd, @OrderDate, GETDATE()) > 7 OR @OrderDate IS NULL
BEGIN
   PRINT 'Invalid Order Date'
   PRINT 'Supplied Order Date was greater than 7 days old '
   PRINT 'or was NULL. Correct the date and resubmit.'
   RETURN @INVALIDDATE
END
-- Skoro zaszlimy do tego miejsca, wszystko musi by w porzdku i moemy przej dalej.
SELECT @InsertedOrderDate =
   CONVERT(datetime, (CONVERT(varchar, @OrderDate, 112)))
   PRINT 'The Time of Day in Order Date was truncated'
/* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
   @InsertedOrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)
-- Przypisz warto bdu do zmiennej lokalnej i sprawd warunek bdu
SELECT @Error = @@ERROR
IF @Error != 0
BEGIN
   -- O nie! Co poszo le.
   IF @Error = 547
   -- Bd naruszenia ograniczenia. Wypisz informacje o moliwych rozwizaniach problemu.
     BEGIN
         PRINT 'Supplied data violates data integrity rules'
         PRINT 'Check that the supplied customer number exists'
         PRINT 'in the system and try again'
     END
     ELSE
     -- Zdarzyo si co nieprzewidzianego, wywietl informacje o nieznanym bdzie.
     BEGIN
         PRINT 'An unknown error occured. Contact your System Administrator'
         PRINT 'The error was number ' + CONVERT(varchar, @Error)
     END
     -- Pomimo wystpienia bdu, przelij fragment kodu do punktu wywoania w celu 
     --poprawienia go z jego poziomu.
     RETURN @Error
END
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY
RETURN



USE Northwind
GO
DECLARE   @MyIdent   int
DECLARE   @MyDate    smalldatetime
DECLARE   @Return    int
SELECT @MyDate = '1/1/1999'
EXEC @Return = spInsertDateValidatedOrder
   @CustomerID = 'ALFKI',
   @EmployeeID = 5,
   @OrderDate  = @MyDate,
   @ShipVia    = 3,
   @Freight    = 5.00,
   @OrderID    = @MyIdent OUTPUT
IF @Return = 0
   SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
   FROM Orders
   WHERE OrderID = @MyIdent
ELSE
   PRINT 'Value Retirned was ' + CONVERT(varchar, @Return)


/* Rczne zgaszanie bdu */


RAISERROR ('Hi there, I''m an error.', 1, 1)

RAISERROR ('This is a sample parametrized %s, along with a zero padding and a sign%+010d',1,1, 'string', 12121)

/* Dodawanie wasnych komunikatw o bdzie */


sp_addmessage
   @msgnum = 60000,
   @severity = 10,
   @msgtext = '%s is not a valid Order date.
Order date must be within 7 days of current date.'


/* Ustawianie puapek bdw*/


USE Northwind
GO
ALTER PROC spInsertDateValidatedOrder
   @CustomerID       nvarchar(5),
   @EmployeeID       int,
   @OrderDate        datetime     = NULL,
   @RequiredDate     datetime     = NULL,
   @ShippedDate      datetime     = NULL,
   @ShipVia	     int,
   @Freight	     money,
   @ShipName         nvarchar(40) = NULL,
   @ShipAddress      nvarchar(60) = NULL,
   @ShipCity         nvarchar(15) = NULL,
   @ShipRegion       nvarchar(15) = NULL,
   @ShipPostalCode   nvarchar(10) = NULL,
   @ShipCountry      nvarchar(15) = NULL,
   @OrderID          int      OUTPUT
AS
-- Deklaracje zmiennych
DECLARE   @Error               int
DECLARE   @BadDate             varchar(12)
DECLARE   @InsertedOrderDate   smalldatetime
/* Sprawd, czy podana data jest starsza ni 7 dni, jeli tak, nie jest duej prawidowa. Sprawd te wystpowanie wartoci NULL. Jeli ktry z warunkw jest prawdziwy, zakocz dziaanie procedury skadowanej wywietlajc informacje o bdzie. */
IF DATEDIFF(dd, @OrderDate, GETDATE()) > 7 OR @OrderDate IS NULL
BEGIN
   -- RAISERROR nie posiada okrelonego typu danych dla daty, wic naley j 
   -- skonwertowa
   SELECT @BadDate = CONVERT(varchar, @OrderDate)
   RAISERROR (60000,1,1, @BadDate) WITH SETERROR
   RETURN @@ERROR
END
-- Skoro zaszlimy do tego miejsca, wszystko musi by w porzdku i moemy przej dalej.
SELECT @InsertedOrderDate =
   CONVERT(datetime, (CONVERT(varchar, @OrderDate, 112)))
   PRINT 'The Time of Day in Order Date was truncated'
/* Stwrz nowy rekord */
INSERT INTO Orders
VALUES
(
   @CustomerID,
   @EmployeeID,
   @InsertedOrderDate,
   @RequiredDate,
   @ShippedDate,
   @ShipVia,
   @Freight,
   @ShipName,
   @ShipAddress,
   @ShipCity,
   @ShipRegion,
   @ShipPostalCode,
   @ShipCountry
)
-- Przypisz warto bdu do zmiennej lokalnej i sprawd warunek bdu
SELECT @Error = @@ERROR
IF @Error != 0
BEGIN
   -- O nie! Co poszo le.
   IF @Error = 547
   -- Bd naruszenia ograniczenia. Wypisz informacje o moliwych rozwizaniach 
   --problemu.
     BEGIN
         PRINT 'Supplied data violates data integrity rules'
         PRINT 'Check that the supplied customer number exists'
         PRINT 'in the system and try again'
     END
     ELSE
     -- Zdarzyo si co nieprzewidzianego, wywietl informacje o nieznanym bdzie.
     BEGIN
         PRINT 'An unknown error occured. Contact your System Administrator'
         PRINT 'The error was number ' + CONVERT(varchar, @Error)
     END
     -- Pomimo wystpienia bdu, przelij fragment kodu do punktu wywoania w celu 
     --poprawienia go z jego poziomu.
     RETURN @Error
END
/* Przenie identyfikator nowego rekordu do zmiennej wyjciowej */
SELECT @OrderID = @@IDENTITY
RETURN


/* Tworzenie wywoywalnych procesw */


USE Northwind
GO
CREATE PROC spTestInsert
   @MyDate   smalldatetime
AS
DECLARE   @MyIdent   int
DECLARE   @Return    int
EXEC @Return = spInsertDateValidatedOrder
   @CustomerID = 'ALFKI',
   @EmployeeID = 5,
   @OrderDate  = @MyDate,
   @ShipVia    = 3,
   @Freight    = 5.00,
   @OrderID    = @MyIdent OUTPUT
IF @Return = 0
   SELECT OrderID, CustomerID, EmployeeID, OrderDate, ShipName
   FROM Orders
   WHERE OrderID = @MyIdent
ELSE
   PRINT 'Error Returned was ' + CONVERT(varchar, @Return)


DECLARE @Today smalldatetime
SELECT @Today = GETDATE()
EXEC spTestInsert
   @MyDate = @Today


EXEC spTestInsert '1/1/1999' --Przykad bdny


/* Procedura skadowana a wydajno */


EXEC spTestInsert '1/1/2004'
   WITH RECOMPILE


/* Krtkie spojrzenie na rekurencj */


CREATE PROC spFactorial
@ValueIn int,
@ValueOut   int OUTPUT
AS
DECLARE @InWorking int
DECLARE @OutWorking int
IF @ValueIn !=1
BEGIN
      SELECT @InWorking = @ValueIn - 1
      EXEC spFactorial @InWorking, @OutWorking OUTPUT
      SELECT @ValueOut = @ValueIn * @OutWorking
END
ELSE
BEGIN
      SELECT @ValueOut = 1
END
RETURN
GO


DECLARE @WorkingOut int
DECLARE @WorkingIn int
SELECT @WorkingIn = 5
EXEC spFactorial @WorkingIn, @WorkingOut OUTPUT
PRINT CAST (@WorkingIn AS varchar) + ' factorial is ' + CAST(@WorkingOut AS varchar)



CREATE PROC spTriangular
@ValueIn int,
@ValueOut   int OUTPUT
AS
DECLARE @InWorking int
DECLARE @OutWorking int
IF @ValueIn !=1
BEGIN
      SELECT @InWorking = @ValueIn - 1
      EXEC spTriangular @InWorking, @OutWorking OUTPUT
      SELECT @ValueOut = @ValueIn + @OutWorking
END
ELSE
BEGIN
      SELECT @ValueOut = 1
END
RETURN
GO


DECLARE @WorkingOut int
DECLARE @WorkingIn int
SELECT @WorkingIn = 5
EXEC spTriangular @WorkingIn, @WorkingOut OUTPUT
PRINT CAST (@WorkingIn AS varchar) + ' Triangular is ' + CAST(@WorkingOut AS varchar)
