Download as pdf or txt
Download as pdf or txt
You are on page 1of 17

GROUP NAME ID NUMBER

1Sani sufiyan…………………….…………….…………………………………………….……………..1182/11

2. Bira Yusuf………………………………………………………………………………………….………..T/1061/12

3.Fita Mohammad………………………….…………………………………………………………….………T/806/12

4. Ahimen Kadir……………………………………………………………………………………………………1142/11

5.Mikael Hanbisa------------------------------------------------------------------------------------1177/11

Submitted To:- Mr. Bilisuma


SUBMISSION DATE 14/05/2021

1
1.What is a SQL server cursor?
A SQL server cursor is a set of T_SQL logic to loop over a predetermined number of rows one at a time.
The purpose for the cursor may be to update one row at a time or perform an administrative process such
as SQL server database backups in a sequential manner. SQL server cursors are used for development,
DBA and ETL processes.

The way to write a cursor in SQL server

 Declare your variables (file names, database names, account numbers, etc.) that you need in the
logic and initialize the variables.
 This logic would be updated based on your needs.
 Declare cursor with a specific name (i.e. db_cursor in this tip) that you will use throughout the
logic along with the business logic (SELECT statement) to populate the records the cursor will
need. The cursor name can be anything meaningful. This is immediately followed by opening the
cursor.
 This logic would be updated based on your needs.
 Fetch a record from cursor to begin the data processing.
 NOTE - There are an equal of number of variables declared for the cursor, columns in the
SELECT statement and variables in the Fetch logic. In the example in this tip there is only one
variable, one column selected and variable fetched, but if five pieces of data were needed for the
cursor then five variables would need to be selected and fetched as well.
 The data process is unique to each set of logic. This could be inserting, updating, deleting, etc. for
each row of data that was fetched. This is the most important set of logic during this process that
is performed on each row.
 This logic would be updated based on your needs.
 Fetch the next record from cursor as you did in step 3 and then step 4 is repeated again by
processing the selected data.
 Once all of the data has been processed, then you close cursor.
 As a final and important step, you need to deal locate the cursor to release all of the internal
resources SQL Server is holding.

Simples examples of SQL server


-- 1 - Declare Variables
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
DECLARE @name VARCHAR(50) -- database name
DECLARE @path VARCHAR(256) -- path for backup files
DECLARE @fileName VARCHAR(256) -- filename for backup
DECLARE @fileDate VARCHAR(20) -- used for file name

-- Initialize Variables
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
SET @path = 'C:\Backup\'

SELECT @fileDate = CONVERT(VARCHAR(20),GETDATE(),112)

-- 2 - Declare Cursor
DECLARE db_cursor CURSOR FOR
-- Populate the cursor with your logic

2
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
SELECT name
FROM MASTER.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb')

-- Open the Cursor


OPEN db_cursor

-- 3 - Fetch the next record from the cursor


FETCH NEXT FROM db_cursor INTO @name

-- Set the status for the cursor


WHILE @@FETCH_STATUS = 0

BEGIN
-- 4 - Begin the custom business logic
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
SET @fileName = @path + @name + '_' + @fileDate + '.BAK'
BACKUP DATABASE @name TO DISK = @fileName

-- 5 - Fetch the next record from the cursor


FETCH NEXT FROM db_cursor INTO @name
END

-- 6 - Close the cursor


CLOSE db_cursor

-- 7 - Deallocate the cursor


DEALLOCATE db_cursor

Explanation of cursor Syntax in SQL server


Based on the example above, cursors include these components:
 DECLARE statements - Declare variables used in the code block
 SET\SELECT statements - Initialize the variables to a specific value
 DECLARE CURSOR statement - Populate the cursor with values that will be evaluated
 NOTE - There are an equal number of variables in the DECLARE CURSOR FOR statement as
there are in the SELECT statement. This could be 1 or many variables and associated columns.
 OPEN statement - Open the cursor to begin data processing
 FETCH NEXT statements - Assign the specific values from the cursor to the variables to match
the DECLARE CURSOR FOR and SELECT statement
 NOTE - This logic is used for the initial population before the WHILE statement and then again
during each loop in the process as a portion of the WHILE statement
 WHILE statement - Condition to begin and continue data processing
 BEGIN...END statement - Start and end of the code block
 NOTE - Based on the data processing, multiple BEGIN...END statements can be used
 Data processing - In this example, this logic is to backup a database to a specific path and file
name, but this could be just about any DML or administrative logic
 CLOSE statement - Releases the current data and associated locks, but permits the cursor to be
re-opened
 DEALLOCATE statement - Destroys the cursor

3
So, why we Use a Cursor in SQL Server?
Although using an INSERT, UPDATE or DELETE statement to modify all of the applicable data in one
transaction is generally the best way to work with data in SQL Server, a cursor may be needed for:

 Iterating over data one row at a time.


 Completing a process in a serial manner such as SQL Server database backups.
 Updating data across numerous tables for a specific account.
 Correcting data with a predefined set of data as the input to the cursor.

A cursor example 2
Let’s start by using a CURSOR, and write the following syntax:

USE AdventureWorks2012
GO
DECLARE @id int

DECLARE cursorT CURSOR


--LOCAL STATIC
--LOCAL FAST_FORWARD
--LOCAL READ_ONLY FORWARD_ONLY
FOR
SELECT ProductId
FROM AdventureWorks2012.Production.Product
WHERE DaysToManufacture <= 1

OPEN cursorT
FETCH NEXT FROM cursorT INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT * FROM Production.ProductInventory
WHERE ProductID=@id
FETCH NEXT FROM cursorT INTO @id
END
CLOSE cursorT
DEALLOCATE cursorT

4
Explanation

After a short coffee break, the query finished executing, returning 833 rows in the time shown below. It’s
important to mention the chosen syntaxes above are only for demo purposes, and I made no index tuning
to speed things up.

In the cursor execution, we have two steps. Step one, the positioning, when the cursor sets its position to a
row from the result set. Step two, the retrieval, when it gets the data from that specific row in an operation
called the FETCH.

In our example, the cursor sets its position to the first row returned by the first SELECT and fetches the
ProductID value that matches WHERE condition in @id variable. Then the second SELECT uses the
variable value to get data from [Production].[ProductInventory] and the next row is fetched. These
operations are repeated until there are no more rows to work with.

Finally, CLOSE syntax releases the current result set and removes the locks from the rows used by the
cursor, and DEALLOCATE removes cursor reference.

Our demo tables are relative small containing roughly 1,000 and 500 rows. If we had to loop through
tables with millions of rows it would last a considerable amount of time and the results would not please
us.

Let’s give our cursor another chance and uncomment the line –LOCAL STATIC. There are many
arguments we can use in a cursor definition, more on that on this link CURSOR Arguments, but for now
let’s focus on what this two words mean.

When we specify LOCAL keyword, the scope of the cursor is local to the batch in which it was created
and it is valid only in this scope. After the batch finishes executing, the cursor is automatically
deallocated. Also, the cursor can be referenced by a stored procedure, trigger or by a local cursor variable
in a batch.

The STATIC keyword makes a temporary copy of the data used by the cursor in tempdb in a temporary
table. Here we have some gotchas. A STATIC cursor is read-only and is also referred to as a snapshot
cursor because it only works with the data from the time it was opened, meaning that it won’t display any
changes made in database on the set of data used by the cursor. Basically, no updates, deletes or inserts
made after the cursor was open will be visible in the cursors result set unless we close and reopen the
cursor.

5
Be aware of this before using these arguments and check if it matches your needs. But let’s see if our
cursor is faster. Below we have the results:

12 seconds are a lot better that 4 minutes and 47 seconds, but keep in mind the restrictions explained above.

If we run the syntax using this argument LOCAL READ_ONLY FORWARD_ONLY we get the same results. READ_ONLY
FORWARD_ONLY cursor can be scrolled only from the first row to the last one. If the STATIC keyword is missing, the cursor
is dynamic and uses a dynamic plan if available. But there are cases when a dynamic plan is worse than a static one.

What happens when we uncomment –LOCAL FAST_FORWARD?


FAST_FORWARD is equivalent to READ_ONLY and FORWARD_ONLY cursor but has the ability to choose
the better plan from either a static or a dynamic one.
LOCAL FAST_FORWARD seems to be the best choice because of its flexibility to choose between a static
or dynamic plan, but FORWARD_ONLY also does the job very good. Although we got the result in an
average of 12 seconds using both of this methods, these arguments should be properly tested before
choosing one of them.

There are many ways of obtaining the same result, much quicker and with less impact on performance.

Cursor alternative
One method is using a JOIN, and as we can see next, the results are considerable better.
First, we have to enable statistics time to measure SQL Server execution time, and make an INNER JOIN
between two tables, [Production].[ProductInventory] and [Production].[Product] on ProductID column.
After hitting the EXECUTE button, we produced the same results in 330 ms, compared to 04:47 time
from the cursor method, and we have a smile on our face.

USE AdventureWorks2012
GO
SET STATISTICS TIME ON
SELECT * FROM Production.ProductInventory as pinv
INNER JOIN Production.Product as pp
ON pinv.ProductID=pp.ProductID
WHERE pp.DaysToManufacture <= 1

6
We do not need to iterate through every row to get what we need, we have no more loops, no while clause, no iterations, we are
working with sets of data instead, getting what we want faster and writing less code.

An appropriate use of cursor


Now that we’ve seen how much damage a cursor can do, let’s see an example where we can make use of
it.
Let’s assume we want to select the size and number of rows for only certain tables from a database. To
achieve this, we will get all table names based on criteria from information_schema.tables and using a
CURSOR we will loop through each of that table name and execute the stored procedure sp_spaceused by
passing one table name at a time to get the information we need.

We will use the same AdventureWorks2012 database, and get all tables from Sales schema that contains
the name ‘Sales‘. For every table name returned, we want to see all the info
from information_schema.tables.

Below we have the T-SQL syntax and the obtained results:

USE AdventureWorks2012
GO
DECLARE @TableName VARCHAR(50) -- table name from 'Sales' schema
DECLARE @Param VARCHAR(50) -- parameter for 'sp_spaceused' procedure

DECLARE db_cursor CURSOR FOR


--select only 'Sales' tables
SELECT TABLE_NAME FROM information_schema.tables
WHERE TABLE_NAME like '%Sales%' and TABLE_TYPE='BASE TABLE'

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @TableName

WHILE @@FETCH_STATUS = 0
BEGIN
--concatenate each table name in a variable and pass it to the stored procedure
SET @Param='Sales.'+@TableName

7
--execute stored procedure for every table name at a time
EXEC sp_spaceused @Param
FETCH NEXT FROM db_cursor INTO @TableName --gets the next table name
END

CLOSE db_cursor
DEALLOCATE db_cursor

This is one method where CURSOR is helpful by iterating through some data one row at a time and gets the result needed. In this
particular case, the cursor gets the job done without having implications on performance and is easy to use.

8
1. Explain how to use data definition language (DDL) trigger to monitor the changes made to
the database objects.

DDL triggers fire in response to a variety of Data Definition Language (DDL) events. These events
primarily correspond to Transact-SQL statements that start with the keywords CREATE, ALTER, DROP,
GRANT, DENY, REVOKE or UPDATE STATISTICS. Certain system stored procedures that perform
DDL-like operations can also fire DDL triggers.

Use DDL triggers when you want to do the following:

a. Prevent certain changes to your database schema.

b. Have something occur in the database in response to a change in your database schema.

c. Record changes or events in the database schema.

Types of DDL Triggers


I. Transact-SQL DDL Trigger

A special type of Transact-SQL stored procedure that executes one or more Transact-SQL statements in
response to a server-scoped or database-scoped event. For example, a DDL Trigger may fire if a
statement such as ALTER SERVER CONFIGURATION is executed or if a table is deleted by using
DROP TABLE.

II.CLR DDL Trigger


Instead of executing a Transact-SQL stored procedure, a CLR trigger executes one or more methods
written in managed code that are members of an assembly created in the .NET Framework and uploaded
in SQL Server.

DDL triggers fire only after the DDL statements that trigger them are run. DDL triggers cannot be used as
INSTEAD OF triggers. DDL triggers do not fire in response to events that affect local or global
temporary tables and stored procedures.
DDL triggers do not create the special inserted and deleted tables.
The information about an event that fires a DDL trigger, and the subsequent changes caused by the
trigger, is captured by using the EVENTDATA function.

Server-scoped DDL triggers appear in the SQL Server Management Studio Object Explorer in
the Triggers folder. This folder is located under the Server Objects folder. Database-scoped DDL
triggers appear in the Database Triggers folder. This folder is located under the Programmability folder
of the corresponding database.

9
DDL Trigger Scope
DDL triggers can fire in response to a Transact-SQL event processed in the current database, or on the
current server. The scope of the trigger depends on the event.

For example, a DDL trigger created to fire in response to a CREATE_TABLE event can do so whenever
a CREATE_TABLE event occurs in the database, or on the server instance. A DDL trigger created to fire
in response to a CREATE_LOGIN event can do so only when a CREATE_LOGIN event occurs in the
server instance.

In the following example, DDL trigger safety will fire whenever


a DROP_TABLE or ALTER_TABLE event occurs in the database.

Copy
CREATE TRIGGER safety
ON DATABASE
FOR DROP_TABLE, ALTER_TABLE
AS
PRINT 'You must disable Trigger "safety" to drop or alter tables!'
ROLLBACK;

In the following example, a DDL trigger prints a message if any CREATE_DATABASE event occurs
on the current server instance. The example uses the EVENTDATA function to retrieve the text of the
corresponding Transact-SQL statement.

Copy
IF EXISTS (SELECT * FROM sys.server_triggers
WHERE name = 'ddl_trig_database')
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
PRINT 'Database Created.'
SELECT
EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarc
har(max)')
GO
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO

10
The lists that map the Transact-SQL statements to the scopes that can be specified for them are available
through the links provided in the section "Selecting a Particular DDL Statement to Fire a DDL Trigger,"
later in this topic.

Database-scoped DDL triggers are stored as objects in the database in which they are created. DDL
triggers can be created in the master database and behave just like those created in user-designed
databases. You can obtain information about DDL triggers by querying the sys.triggers catalog view.
You can query sys.triggers within the database context in which the triggers are created or by specifying
the database name as an identifier, such as master.sys.triggers.

Server-scoped DDL triggers are stored as objects in the master database. However, you can obtain
information about server-scoped DDL triggers by querying the sys.server_triggers catalog view in any
database context.

2. Write a trigger to ensure that no Student of age less than 15 and greater than
40 can be inserted in the database which will work before insertion in Student
table and create a duplicate copy of the record in another table Student_backup.

CREATE DATABASE databaseITsecondyr;


Create table Student_backup
(Student _no int,
Student _name varchar(20),
Course varchar(40),
primary key(Student_id));

delimiter $$
CREATE TRIGGER Backup BEFORE INSERT ON Student
FOR EACH ROW
BEGIN
IF (NEW.age < 15)
AND (NEW.age>40)
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'ERROR:
'AGE MUST BE LESS THAN 15 AND GREATER THAN YEARS!';
THEN
INSERT INTO Student _backup
VALUES (OLD. Student _no, OLD.name, OLD.Course);
END; $$
delimiter;

Explanation: we create a trigger named Backup that will be executed before the insertion of any
Tupple from the table employee. Before insertion, the values of all the attributes of the table employee
will be stored in the table employee_backup.

11
3. Illustrate how to define, begin, commit and rollback Transaction in sql Server with
executable tsql code.

What does BEGIN TRAN, ROLLBACK TRAN, and COMMIT TRAN mean?
The following example answers the above question clearly.
Let say we are creating a SQL Statement by default, for example, SELECT * FROM Human
Resources.Employee, SQL Server will run this statement and immediately return the results:

SELECT *FROM HumanResource

If you were to add BEGIN TRANSACTION (or BEGIN TRAN) before the statement it automatically makes
the transaction explicit and holds a lock on the table until the transaction is either committed or rolled back.

BEGIN TRANSACTION marks the starting point of an explicit, local transaction. - MS

For example, when I issue a DELETE or UPDATE statement I always explicitly use BEGIN TRAN to make
sure my statement is correct and I get the correct number of results returned.

Let’s say I want to UPDATE the Employee table and set JobTitle equal to 'DBA' where LoginID is like
'%barbara%'. I accidentally create my statement wrong and issue the statement below which actually would
make every JobTitle equal to 'DBA':

UPDATE HumanResources.Employee
SET JobTitle = ‘DBA’
WHERE LoginID IN (
SELECT LoginID FROM HumanResources.Employee)

12
Oops! I didn’t mean to do that!! I accidentally made every record have a JobTitle of DBA. If I would have
placed a BEGIN TRAN before my statement I would have noticed that 290 results would be affected and
something is wrong with my statement:

BEGIN TRAN
UPDATE HumanResources.Employee
SET Job title=’DBA’
WHERE LoginID IN (
SELECT LoginID FROM HumanResources.Employee)

13
Since I specified a BEGIN TRAN, the transaction is now waiting on a ROLLBACK or COMMIT. While the
transaction is waiting it has created a lock on the table and any other processes that are trying to access
HumanResources.Employee are now being blocked. Be careful using BEGIN TRAN and make sure you
immediately issue a ROLLBACK or COMMIT:

As you can see, SPID 52 is getting blocked by 54.

Since I noticed something was terribly wrong with my UPDATE statement, I can issue a
ROLLBACK TRAN statement to rollback the transaction meaning that none of the data actually
changed:

ROLLBACK TRANSACTION rolls back an explicit or implicit transaction to the beginning of


the transaction, or to a savepoint inside the transaction. It also frees resources held by the
transaction. - MS

BEGIN TRAN
UPDATE HumanResources.Employee
SET Job title=’DBA’
WHERE LoginID IN (
SELECT LoginID FROM HumanResources.Employee)
ROLLBACK TRAN
SELECT LoginID , JobTitle FROM HumanResources.Employee

14
If I had written my statement correct the first time and noticed the right amount of results
displayed then I could issue a COMMIT TRAN and it would execute the statement and my
changes would be committed to the database:

COMMIT TRANSACTION marks the end of a successful implicit or explicit transaction. If


@@TRANCOUNT is 1, COMMIT TRANSACTION makes all data modifications performed since the
start of the transaction a permanent part of the database, frees the resources held by the transaction,
and decrements @@TRANCOUNT to 0. If @@TRANCOUNT is greater than 1, COMMIT
TRANSACTION decrements @@TRANCOUNT only by 1 and the transaction stays active. - MS

BEGIN TRAN
UPDATE HumanResources.Employee
SET Job title=’DBA’
WHERE LoginID IN (
SELECT LoginID FROM HumanResources.Employee WHERE LoginID LIKE ‘%barbara%’)
COMMIT TRAN

SELECT LoginID, JobTitle FROM HumanResources.Employee WHERE LoginID LIKE


‘%barbara%’

Syntax

15
4. What are the DCL Commands? How can we use DCL commands to enforce database
security in a multiple user database evironment? explain briefly with t-sql executable code.

Overview of Sequential Query Language (SQL)


 It is the most widely used programming language for managing data in a relational
database management system.
 It is also used for stream processing in a relational data stream management system.

 Oracle Database, MySQL, Microsoft SQL Server, PostgreSQL, and MariaDB are some
of the most popular relational database management systems.
 SQL commands are used for communicating with the database.
 Everything ranging from creating a table and adding data to modifying a table and setting user
permissions is accomplished using Basic SQL commands.
 There are five types of SQL commands: DDL, DML, DCL, TCL, and DQL.
But for now we are going to discuss DCL commands only.

Why we use DCL commands?


In order to protect the information in a table from unauthorized access, DCL commands are used.
A DCL command can either enable or disable a user from accessing information from a database.

DCL includes commands such as GRANT and REVOKE which mainly deal with the rights,
permissions and other controls of the database system.

DCL commands are used to enforce database security in a multiple database


environment. Database Administrator's or owner's of the database object can provide/remove privileges
on a database object. SQL Grant command is used to provide access or privileges on the database objects
to the users.

Examples of DCL commands:


 GRANT-gives user’s access privileges to the database.
 REVOKE-withdraw user’s access privileges given by using the GRANT command.

List of user access privileges:

 ALTER
 DELETE
 INDEX
 INSERT
 SELECT
 UPDATE

General Syntax for Grant:

16
GRANT object_privileges ON table_name TO user_name1, user_name2,….,user_nameN;
GRANT object_privileges ON table_name TO user_name1, user_name2,….,user_nameN WITH GRANT
OPTION; (allows the grantee to grant user access privileges to others)

Example 1:
GRANT SELECT, UPDATE ON Student TO Akhil Bhadwal

This will allow the user to run only SELECT and UPDATE operations on the Student table.
Example 2:

GRANT ALL ON Student TO Akhil Bhadwal WITH GRANT OPTION


Allows the user to run all commands on the table as well as grant access privileges to other users.

General Syntax REVOKE

Used for taking back permission given to a user.

REVOKE object_privileges ON table_name FROM user1, user2,… userN;

Example:
REVOKE UPDATE ON Student FROM Akhil;

Note: - A user who is not the owner of a table but has been given the privilege to grant permissions to
other users can also revoke permissions.

17

You might also like