SQL Complete Guide
SQL Complete Guide
SQL
Ankit Pandey
Table of Contents
About 1
Chapter 1: Getting started with SQL 2
Remarks 2
Versions 2
Examples 2
2
Overview
4
Chapter 2: ALTER TABLE 4
Introduction 4
Syntax 4
Examples 4
Add Column(s) 4
Drop Column 4
Drop Constraint 4
Add Constraint 5
Alter Column 5
Examples
Sample data 13
Query 13
Results 14
Explanation 14
Introduction 15
Examples 15
15
Formatting and Spelling of Keywords and Names
15
Table/Column Names
15
Keywords
15
SELECT *
16
Indenting
17
Joins 19
19
Chapter 7: Comments
19
Examples
19
Single-line comments
20
Multi-line comments 20
Syntax 20
Remarks 20
Examples 21
Temporary query 21
generating values 23
Introduction 30
Syntax 30
Parameters 30
Remarks 30
31
Examples
31
Create a New Table
31
Create Table From Select
32
Duplicate a table
32
CREATE TABLE With FOREIGN KEY
Examples
DECIMAL and NUMERIC 36
Integers 36
UNIQUEIDENTIFIER 38
39
Chapter 14: DELETE
39
Introduction
39
Syntax
39
Examples
39
DELETE certain rows with WHERE
39
DELETE all rows
39
TRUNCATE clause
39
DELETE certain rows based upon comparisons with other tables 41
Chapter 15: DROP or DELETE Database 41
Syntax 41
Remarks 41
41
Examples
42
DROP Database 42
Remarks 42
Examples 42
Simple drop
43
43
Check for existence before dropping 43
43
Examples
44
Auto Shop Database
Departments
Employees
Customers 44
Cars 45
46
Library Database
46
Relationships between tables
46
Authors
47
Books
48
BooksAuthors
49
Examples
49
Countries Table 49
51
Countries
51
Chapter 18: EXCEPT
51
Remarks 51
52
Examples
52
Select dataset except where values are in this other dataset 52
53
Chapter 19: Execution blocks 53
53
Examples
53
Using BEGIN ... END
53
Chapter 20: EXISTS CLAUSE
54
Examples
55
EXISTS CLAUSE
55
Get all customers with a least one order
55
Get all customers with no order 55
Purpose 56
56
Chapter 21: EXPLAIN and DESCRIBE
56
Examples
56
DESCRIBE tablename;
Syntax
Examples
The WHERE clause only returns rows that match its criteria
Use IN to return rows with a value contained in a list 56
Equality 59
AND and OR 60
Where EXISTS 62
63
Chapter 23: Finding Duplicates on a Column Subset with Detail
63
Remarks
63
Examples
63
Students with same name and date of birth 64
64
Chapter 24: Foreign Keys 64
Examples 64
Examples 67
SUM 68
Conditional aggregation 68
AVG() 68
EXAMPLE TABLE 69
QUERY 69
69
RESULTS
69
List Concatenation
69
MySQL
PostgreSQL
SQL Server 69
Introduction 73
Syntax 73
Examples 73
74
FIRST_VALUE
74
LAST_VALUE
75
LAG and LEAD
76
PERCENT_RANK and CUME_DIST
79
PERCENTILE_DISC and PERCENTILE_CONT
79
Chapter 27: Functions (Scalar/Single Row)
79
Introduction
79
Syntax
80
Remarks
80
Examples
80
Character modifications 82
Date And Time 83
Configuration and Conversion Function 83
Logical and Mathmetical Function 84
SQL has two logical functions – CHOOSE and IIF. 85
SQL includes several mathematical functions that you can use to perform calculations on in 85
85
Chapter 28: GRANT and REVOKE
85
Syntax
Remarks
Examples
Grant/revoke privileges 85
86
Chapter 29: GROUP BY
86
Introduction
86
Syntax
86
Examples
86
USE GROUP BY to COUNT the number of rows for each unique entry in a given column
88
Filter GROUP BY results using a HAVING clause
88
Basic GROUP BY example
89
ROLAP aggregation (Data Mining)
89
Description
90
Examples
90
With cube
90
With roll up 92
Introduction 92
92
Examples 93
Unquoted identifiers 93
93
Chapter 31: IN clause
93
Examples
94
Simple IN clause 94
Using IN clause with a subquery 94
Chapter 32: Indexes 94
Introduction 94
Remarks 95
Examples 96
Creating an Index 96
Sorted Index
Clustered index 97
Introduction 102
Syntax 102
Remarks 102
103
Examples
103
Basic explicit inner join
104
Implicit Join 106
Left Outer Join 106
108
So how does this work?
109
Self Join
109
So how does this work?
111
CROSS JOIN
112
Joining on a Subquery
112
CROSS APPLY & LATERAL JOIN
FULL JOIN
Recursive JOINs
PostgreSQL example
Chapter 38: MERGE 123
Introduction 123
Examples 123
123
MERGE to make Target match Source
123
MySQL: counting users by name
124
PostgreSQL: counting users by name
125
Chapter 39: NULL
125
Introduction
125
Examples
125
Filtering for NULL in queries 125
Nullable columns in tables 126
Updating fields to NULL 126
Inserting rows with NULL fields 127
127
Chapter 40: ORDER BY
127
Examples
128
Use ORDER BY with TOP to return the top x rows based on a column's value
128
Sorting by multiple columns
129
Sorting by column number (instead of name)
129
Order by Alias 131
Customizeed sorting order 131
131
Chapter 41: Order of Execution 133
133
Examples
133
Logical Order of Query Processing in SQL
133
Chapter 42: Primary Keys
133
Syntax
135
Examples 135
135
Creating a Primary Key
135
Using Auto Increment
Examples
Overview
SELECT
PROJECT 136
GIVING 136
ALIAS 138
DIVIDE 138
UNION 138
INTERSECTION 138
DIFFERENCE 138
UPDATE ( := ) 138
TIMES 138
Syntax 140
Examples 140
140
Row numbers without partitions
140
Row numbers with partitions
140
Delete All But Last Record (1 to Many Table)
141
Chapter 45: SELECT
141
Introduction
141
Syntax
141
Remarks
141
Examples
141
Using the wildcard character to select all columns in a query. 142
Simple select statement 142
Dot notation 143
When Can You Use *, Bearing The Above Warning In Mind? 144
Selecting with Condition 144
Select Individual Columns 145
SELECT Using Column Aliases 145
152
Average
152
Minimum
153
Maximum
153
Count
153
Sum
153
Selecting with null Selecting with CASE Selecting
154
without Locking the table Select distinct (unique
154
values only) Select with condition of multiple values
155
from column Get aggregated result for row groups
155
Selecting with more than 1 condition.
155
156
158
Chapter 46: Sequence 158
158
Examples
158
Create Sequence
159
Using Sequences 159
159
Examples
160
Skipping some rows from result
161
Limiting amount of results 161
Skipping then taking some results (Pagination) 161
Examples
Example of a cursor that queries all rows by index for each database
Chapter 49: SQL Group By vs Distinct 163
163
Examples
163
Difference between GROUP BY and DISTINCT 165
165
Chapter 50: SQL Injection
165
Introduction
165
Examples
166
SQL injection sample
168
simple injection sample 168
Chapter 51: Stored Procedures 168
Remarks 168
169
Examples
169
Create and call a stored procedure
169
Chapter 52: String Functions
169
Introduction
169
Syntax
169
Remarks
170
Examples 170
Concatenate 171
Substring 171
Split 172
Stuff 172
Length 173
Replace 173
REVERSE 173
REPLICATE 174
REGEXP 175
PARSENAME
INSTR
Chapter 53: Subqueries 176
Remarks 176
Examples 176
176
Subquery in WHERE clause
176
Subquery in FROM clause
176
Subquery in SELECT clause
176
Subqueries in FROM clause
177
Subqueries in WHERE clause
177
Subqueries in SELECT clause
178
Filter query results using query on different table
178
Correlated Subqueries
179
Chapter 54: Synonyms 179
179
Examples
180
Create Synonym 180
Remarks 180
182
Examples
182
Properties of a well designed table.
182
Chapter 56: Transactions 182
Remarks 182
Examples 183
183
Simple Transaction
183
Rollback Transaction
183
Chapter 57: Triggers 184
Examples 184
Introduction
Syntax
Remarks
Examples
Removing all rows from the Employee table 184
186
Chapter 59: TRY/CATCH
186
Remarks
186
Examples 186
Transaction In a TRY/CATCH 187
187
Chapter 60: UNION / UNION ALL
187
Introduction
187
Syntax
187
Remarks
187
Examples
188
Basic UNION ALL query
190
Simple explanation and Example 190
Syntax 190
Examples 190
191
SQL:2003 192
193
SQL Server 193
193
Chapter 62: Views
194
Examples 194
Examples
Examples
Overview
Structured Query Language (SQL) is a special-purpose programming language designed for
managing data held in a Relational Database Management System (RDBMS). SQL-like languages
can also be used in Relational Data Stream Management Systems (RDSMS), or in "not-only SQL"
(NoSQL) databases.
SQL comprises of 3 major sub-languages:
1. Data Definition Language (DDL): to create and modify the structure of the database;
2. Data Manipulation Language (DML): to perform Read, Insert, Update and Delete operations
https://riptutorial.com/ 2
on the data of the database;
3. Data Control Language (DCL): to control the access of the data stored in the database.
The core DML operations are Create, Read, Update and Delete (CRUD for short) which are
performed by the statements INSERT, SELECT, UPDATE and DELETE.
There is also a (recently added) MERGE statement which can perform all 3 write operations
(INSERT, UPDATE, DELETE).
CRUD article on Wikipedia
Many SQL databases are implemented as client/server systems; the term "SQL server" describes
such a database.
At the same time, Microsoft makes a database that is named "SQL Server". While that database
speaks a dialect of SQL, information specific to that database is not on topic in this tag but belongs
into the SQL Server documentation.
https://riptutorial.com/ 3
Chapter 2: ALTER TABLE
Introduction
ALTER command in SQL is used to modify column/constraint in a table
Syntax
Examples
Add Column(s)
The above statement would add columns named StartingDate which cannot be NULL with default
value as current date and DateOfBirth which can be NULL in Employees table.
Drop Column
This will not only delete information from that column, but will drop the column salary from table
employees(the column will no more exist).
Drop Constraint
This Drops a constraint called DefaultSalary from the employees table definition.
Note:- Ensure that constraints of the column are dropped before dropping a column.
Add Constraint
This adds a constraint called DefaultSalary which specifies a default of 100 for the Salary column.
https://riptutorial.com/ 4
A constraint can be added at the table level.
Types of constraints
Alter Column
This query will alter the column datatype of StartingDate and change it from simple date to datetime
and set default to current date.
Add Primary Key
This will add a Primary key to the table Employees on the field ID. Including more than one column
name in the parentheses along with ID will create a Composite Primary Key. When adding more
than one column, the column names must be separated by commas.
https://riptutorial.com/ 5
Chapter 3: AND & OR Operators
Syntax
Examples
AND OR Example
Have a table
Bob 10 Paris
Mat 20 Berlin
Mary 24 Prague
Gives
Name
Mary
Gives
Name
Bob
Mary
https://riptutorial.com/ 6
Chapter 4: Cascading Delete
Examples
ON DELETE CASCADE
Assume you have a application that administers rooms.
Assume further that your application operates on a per client basis (tenant).
You have several clients.
So your database will contain one table for clients, and one for rooms.
Now, every client has N rooms.
This should mean that you have a foreign key on your room table, referencing the client table.
ALTER TABLE dbo.T_Room WITH CHECK ADD CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
GO
Assuming a client moves on to some other software, you'll have to delete his data in your
software. But if you do
Then you'll get a foreign key violation, because you can't delete the client when he still has rooms.
Now you'd have write code in your application that deletes the client's rooms before it deletes the
client. Assume further that in the future, many more foreign key dependencies will be added in
your database, because your application's functionality expands. Horrible. For every modification
in your database, you'll have to adapt your application's code in N places. Possibly you'll have to
adapt code in other applications as well (e.g. interfaces to other systems).
ALTER TABLE dbo.T_Room -- WITH CHECK -- SQL-Server can specify WITH CHECK/WITH NOCHECK
ADD CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
ON DELETE CASCADE
and the rooms are automagically deleted when the client is deleted.
Problem solved - with no application code changes.
https://riptutorial.com/ 7
One word of caution: In Microsoft SQL-Server, this won't work if you have a table that references
itselfs. So if you try to define a delete cascade on a recursive tree structure, like this:
it won't work, because Microsoft-SQL-server doesn't allow you to set a foreign key with ON DELETE
CASCADE on a recursive tree structure. One reason for this is, that the tree is possibly cyclic, and
that would possibly lead to a deadlock.
PostgreSQL on the other hand can do this;
the requirement is that the tree is non-cyclic.
If the tree is cyclic, you'll get a runtime error.
In that case, you'll just have to implement the delete function yourselfs.
A word of caution:
This means you can't simply delete and re-insert the client table anymore, because if you do this,
it will delete all entries in "T_Room"... (no non-delta updates anymore)
https://riptutorial.com/ 8
Chapter 5: CASE
Introduction
The CASE expression is used to implement if-then logic.
Syntax
•CASE input_expression
WHEN compare1 THEN result1
[WHEN compare2 THEN result2]...
[ELSE resultX]
END
• CASE
WHEN condition1 THEN result1
[WHEN condition2 THEN result2]...
[ELSE resultX]
END
Remarks
The simple CASE expression returns the first result whose
compareXvalue is equal to the
input_expression.
The searched CASE expression returns the first result whose is true.
conditionX
Examples
Searched CASE in SELECT (Matches a boolean expression)
The searched CASE returns results when a boolean expression is TRUE.
(This differs from the simple case, which can only check for equivalency with an input.)
https://riptutorial.com/ 9
I ItemI Price PriceRating
4 145 10 AFFORDABLE
5
Use CASE to COUNT the number of rows in a column match a condition.
Use Case
CASE can be used in conjunction with SUM to return a count of only those items matching a pre-
defined condition. (This is similar to COUNTIF in Excel.)
The trick is to return binary results indicating matches, so the "1"s returned for matching entries
can be summed for a count of the total number of matches.
Given this table ItemSales, let's say you want to learn the total number of items that have been
categorized as "Expensive":
5 145 10 AFFORDABLE
Query
SELECT
COUNT(Id) AS ItemsCount,
SUM ( CASE
WHEN PriceRating = 'Expensive' THEN 1
ELSE 0
END
) AS ExpensiveItemsCount
FROM ItemSales
Results:
ItemsCount ExpensiveItemsCount
5 3
https://riptutorial.com/ 10
Alternative:
SELECT
COUNT(Id) as ItemsCount,
SUM (
CASE PriceRating
WHEN 'Expensive' THEN 1
ELSE 0
END
) AS ExpensiveItemsCount
FROM ItemSales
CASE's shorthand variant evaluates an expression (usually a column) against a series of values.
This variant is a bit shorter, and saves repeating the evaluated expression over and over again.
The ELSE clause can still be used, though:
A word of caution. It's important to realize that when using the short variant the entire statement is
evaluated at each WHEN . Therefore the following statement:
SELECT
CASE ABS(CHECKSUM(NEWID())) % 4
WHEN 0 THEN 'Dr'
WHEN 1 THEN 'Master'
WHEN 2 THEN 'Mr'
WHEN 3 THEN 'Mrs'
END
may produce a NULLresult. That is because at each is being called again with a new
WHEN NEWID()
SELECT
CASE
WHEN ABS(CHECKSUM(NEWID())) % 4 = 0 THEN 'Dr'
WHEN ABS(CHECKSUM(NEWID())) % 4 = 1 THEN 'Master'
WHEN ABS(CHECKSUM(NEWID())) % 4 = 2 THEN 'Mr'
WHEN ABS(CHECKSUM(NEWID())) % 4 = 3 THEN 'Mrs'
END
Therefore it can miss all the WHEN cases and result as NULL.
https://riptutorial.com/ 11
SELECT * FROM DEPT
ORDER BY
CASE DEPARTMENT
WHEN 'MARKETING' THEN 1
WHEN 'SALES' THEN 2
WHEN 'RESEARCH' THEN 3
WHEN 'INNOVATION' THEN 4
ELSE 5
END,
CITY
UPDATE ItemPrice
SET Price = Price *
CASE ItemId
WHEN 1 THEN 1.05
WHEN 2 THEN 1.10
WHEN 3 THEN 1.15
ELSE 1.00
END
in this way '0' representing the known values are ranked first, '1' representing the NULL values are
sorted by the last:
SELECT ID
,REGION
,CITY
,DEPARTMENT
,EMPLOYEES_NUMBER
https://riptutorial.com/ 12
FROM DEPT
ORDER BY
CASE WHEN REGION IS NULL THEN 1
ELSE 0
END,
REGION
ID REGION
10 Mid- CITY DEPARTMENT EMPLOYEES_NUMBER
42 Chicago INNOVATION
Imagine that you need sort records by lowest value of either one of two columns. Some databases
could use a non-aggregated MIN() or LEAST() function for this (... ORDER BY MIN(Date1, Date2)), but
in standard SQL, you have to use a CASE expression.
The CASE expression in the query below looks at the Date1 and Date2 columns, checks which
column has the lower value, and sorts the records depending on this value.
Sample data
Id Date1 Date2
1 2017-01- 2017-01-
2 01 2017- 31 2017-
3 01-31 01-03
4 2017-01- 2017-01-
5 31 2017- 02 2017-
6 01-06 01-31
2017-01- 2017-01-
https://riptutorial.com/ 13
Query
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN COALESCE(Date1, '1753-01-01') < COALESCE(Date2, '1753-01-01') THEN Date1
ELSE Date2
END
Results
Id Date1 Date2
1 2017-01- 2017-01-
3 01 2017- 31 2017-
2 01-31 01-02
2017-01-
6 2017-01- 03 2017-
5 31 2017- 01-31
4 01-04 2017-01-
2017-01- 05 2017-
Explanation
31 2017- 01-31
As you see row with Id = 1 is first, that because Date1 have lowest record from entire table 2017-
01-01,01-06
row where Id = 3 is second that because Date2 equals to 2017-01-02 that is second lowest
value from table and so on.
So we have sorted records from 2017-01-01 to 2017-01-06 ascending and no care on which one
column Date1 or Date2 are those values.
Read CASE online: https://riptutorial.com/sql/topic/456/case
https://riptutorial.com/ 14
Chapter 6: Clean Code in SQL
Introduction
How to write good, readable SQL queries, and example of good practices.
Examples
Formatting and Spelling of Keywords and Names
Table/Column Names
Two common ways of formatting table/column names are
CamelCase and snake_case:
Names should describe what is stored in their object. This implies that column names usually
should be singular. Whether table names should use singular or plural is a heavily discussed
question, but in practice, it is more common to use plural table names.
Adding prefixes or suffixes like tbl or col reduces readability, so avoid them. However, they are
sometimes used to avoid conflicts with SQL keywords, and often used with triggers and indexes
(whose names are usually not mentioned in queries).
Keywords
SQL keywords are not case sensitive. However, it is common practice to write them in upper case.
SELECT *
SELECT * returns all columns in the same order as they are defined in the table.
When using SELECT *, the data returned by a query can change whenever the table definition
changes. This increases the risk that different versions of your application or your database are
incompatible with each other.
Furthermore, reading more columns than necessary can increase the amount of disk and network
I/O.
https://riptutorial.com/
15
So you should always explicitly specify the column(s) you actually want to retrieve:
--SELECT * don't
SELECT ID, FName, LName, PhoneNumber -- do
FROM Emplopees;
However, SELECT * does not hurt in the subquery of an EXISTS operator, because EXISTS ignores
the actual data anyway (it checks only if at least one row has been found). For the same reason, it
is not meaningful to list any specific column(s) for EXISTS, so SELECT * actually makes more
sense:
Indenting
There is no widely accepted standard. What everyone agrees on is that squeezing everything into
a single line is bad:
At the minimum, put every clause into a new line, and split lines if they would become too long
otherwise:
SELECT d.Name,
COUNT(*) AS Employees
FROM Departments AS d JOIN Employees AS e ON
d.ID = e.DepartmentID WHERE d.Name != 'HR' HAVING
COUNT(*) > 10 ORDER BY COUNT(*) DESC;
Sometimes, everything after the SQL keyword introducing a clause is indented to the same
column:
d.Name,
SELECT
FROM
COUNT(*) AS Employees
JOIN
Departments AS d
WHERE
Employees AS e ON d.ID = e.DepartmentID
HAVING != 'HR'
d.Name
COUNT(*) > 10
ORDER BY COUNT(*) DESC;
https://riptutorial.com/ 16
(This can also be done while aligning the SQL keywords right.)
SELECT
d.Name,
COUNT(*) AS Employees
FROM
Departments AS d
JOIN
Employees AS e
ON d.ID = e.DepartmentID
WHERE
d.Name != 'HR'
HAVING
COUNT(*) > 10
ORDER BY
COUNT(*) DESC;
SELECT Model,
EmployeeID
FROM Cars
WHERE CustomerID = 42
AND Status = 'READY';
Using multiple lines makes it harder to embed SQL commands into other programming languages.
However, many languages have a mechanism for multi-line strings, e.g., @"..." in C#, """...""" in
Python, or R"(...)" in C++.
Joins
Explicit joins should always be used; implicit joins have several problems:
•The join condition is somewhere in the WHERE clause, mixed up with any other filter
conditions. This makes it harder to see which tables are joined, and how.
•Due to the above, there is a higher risk of mistakes, and it is more likely that they are found
later.
•In standard SQL, explicit joins are the only way to use outer joins:
SELECT d.Name,
e.Fname || e.LName AS EmpName
FROM Departments AS d
LEFT JOIN Employees AS e ON d.ID = e.DepartmentID;
SELECT RecipeID,
https://riptutorial.com/ 17
Recipes.Name,
FROM COUNT(*) AS NumberOfIngredients
Recipes
LEFT JOIN Ingredients USING (RecipeID);
(This requires that both tables use the same column name.
USING automatically removes the duplicate column from the result, e.g., the join in this
query returns a single RecipeID column.)
https://riptutorial.com/ 18
Chapter 7: Comments
Examples
Single-line comments
Single line comments are preceded by
SELECT *
FROM Employees -- this is a comment
WHERE FName = 'John'
Multi-line comments
Multi-line code comments are wrapped in
/* ... */:
/* This query
returns all employees */
SELECT *
FROM Employees
https://riptutorial.com/ 19
Chapter 8: Common Table Expressions
Syntax
Remarks
Official documentation: WITH clause
A Common Table Expression is a temporary result set, and it can be result of complex sub query.
It is defined by using WITH clause. CTE improves readability and it is created in memory rather
than TempDB database where Temp Table and Table variable is created.
•Can be used to break up complex queries, especially complex joins and sub-queries.
•Is a way of encapsulating a query definition.
•Persist only until the next query is run.
•Correct use can lead to improvements in both code quality/maintainability and speed.
•Can be used to reference the resulting table multiple times in the same statement (eliminate
duplication in SQL).
•Can be a substitute for a view when the general use of a view is not required; that is, you do
not have to store the definition in metadata.
•Will be run when called, not when defined. If the CTE is used multiple times in a query it will
be run multiple times (possibly with different results).
Examples
Temporary query
These behave in the same manner as nested subqueries but with a different syntax.
WITH ReadyCars AS (
SELECT *
https://riptutorial.com/ 20
FROM Cars
WHERE Status = 'READY'
)
SELECT ID, Model, TotalCost
FROM ReadyCars
ORDER BY TotalCost;
ID Model TotalCost
2 Ford F-150
ON Employees.ID = ManagersOfJonathon.ManagerID
)
SELECT * FROM ManagersOfJonathon;
2
1 James Smith 1234567890 N 1
U L
generating values
L
Most databases do not have a native way of generating a series of numbers for ad-hoc use;
https://riptutorial.com/ 21
however, common table expressions can be used with recursion to emulate that type of function.
The following example generates a common table expression called Numbers with a column i which
has a row for numbers 1-5:
--Give a table name `Numbers" and a column `i` to hold the numbers
WITH Numbers(i) AS (
--Starting number/index
SELECT 1
--Top-level UNION ALL operator required for recursion
UNION ALL
--Iteration expression:
SELECT i + 1
--Table expression we first declared used as source for recursion
FROM Numbers
--Clause to define the end of the recursion
WHERE i < 5
)
--Use the generated table expression like a regular table
SELECT i FROM Numbers;
This method can be used with any number interval, as well as other types of data.
Employees.ID,
Employees.FName,
Employees.LName
FROM Employees
JOIN ManagedByJames
ON Employees.ManagerID = ManagedByJames.ID
https://riptutorial.com/ 22
)
SELECT * FROM ManagedByJames;
1 1 James Smith
2 2 John Johnson
3 4 Johnathon Smith
2 3 Michael Williams
Oracle's CONNECT BY functionality provides many useful and nontrivial features that are not
built-in when using SQL standard recursive CTEs. This example replicates these features (with a
few additions for sake of completeness), using SQL Server syntax. It is most useful for Oracle
developers finding many features missing in their hierarchical queries on other databases, but it
also serves to showcase what can be done with a hierarchical query in general.
WITH tbl AS (
SELECT id, name, parent_id
FROM mytable)
, tbl_hierarchy AS (
/* Anchor */
SELECT 1 AS "LEVEL"
--, 1 AS CONNECT_BY_ISROOT
--, 0 AS CONNECT_BY_ISBRANCH
, CASE WHEN t.id IN (SELECT parent_id FROM tbl) THEN 0 ELSE 1 END AS
CONNECT_BY_ISLEAF
, 0 AS CONNECT_BY_ISCYCLE
, '/' + CAST(t.id AS VARCHAR(MAX)) + '/' AS SYS_CONNECT_BY_PATH_id
, '/' + CAST(t.name AS VARCHAR(MAX)) + '/' AS SYS_CONNECT_BY_PATH_name
, t.id AS root_id
, t.*
FROM tbl t
WHERE t.parent_id IS NULL -- START WITH parent_id IS NULL
UNION ALL
/* Recursive */
SELECT th."LEVEL" + 1 AS "LEVEL"
--, 0 AS CONNECT_BY_ISROOT
--, CASE WHEN t.id IN (SELECT parent_id FROM tbl) THEN 1 ELSE 0 END AS
CONNECT_BY_ISBRANCH
, CASE WHEN t.id IN (SELECT parent_id FROM tbl) THEN 0 ELSE 1 END AS
CONNECT_BY_ISLEAF
, CASE WHEN th.SYS_CONNECT_BY_PATH_id LIKE '%/' + CAST(t.id AS VARCHAR(MAX)) +
'/%' THEN 1 ELSE 0 END AS CONNECT_BY_ISCYCLE
, th.SYS_CONNECT_BY_PATH_id + CAST(t.id AS VARCHAR(MAX)) + '/' AS
SYS_CONNECT_BY_PATH_id
, th.SYS_CONNECT_BY_PATH_name + CAST(t.name AS VARCHAR(MAX)) + '/' AS
SYS_CONNECT_BY_PATH_na
me , th.root_id , t.*
FROM tbl t
https://riptutorial.com/ 23
JOIN tbl_hierarchy th ON (th.id = t.parent_id) -- CONNECT BY PRIOR id =
parent_id
WHERE th.CONNECT_BY_ISCYCLE = 0) -- NOCYCLE
SELECT th.*
--, REPLICATE(' ', (th."LEVEL" - 1) * 3) + th.name AS tbl_hierarchy
FROM tbl_hierarchy th
JOIN tbl CONNECT_BY_ROOT ON (CONNECT_BY_ROOT.id = th.root_id)
ORDER BY th.SYS_CONNECT_BY_PATH_name; -- ORDER SIBLINGS BY name
• Clauses
○CONNECT BY: Specifies the relationship that defines the hierarchy.
○START WITH: Specifies the root nodes.
○ORDER SIBLINGS BY: Orders results properly.
• Parameters
○NOCYCLE: Stops processing a branch when a loop is detected. Valid hierarchies are
Directed Acyclic Graphs, and circular references violate this construct.
• Operators
○PRIOR: Obtains data from the node's parent.
○CONNECT_BY_ROOT: Obtains data from the node's root.
• Pseudocolumns
○LEVEL: Indicates the node's distance from its root.
○CONNECT_BY_ISLEAF: Indicates a node without children.
○CONNECT_BY_ISCYCLE: Indicates a node with a circular reference.
• Functions
○SYS_CONNECT_BY_PATH: Returns a flattened/concatenated representation of the
path to the node from its root.
https://riptutorial.com/ 24
RosterEnd,
CASE TeamA WHEN 1 THEN 'RR' WHEN 2 THEN 'DS' WHEN 3 THEN 'NS' END AS TeamA,
CASE TeamB WHEN 1 THEN 'RR' WHEN 2 THEN 'DS' WHEN 3 THEN 'NS' END AS TeamB,
CASE TeamC WHEN 1 THEN 'RR' WHEN 2 THEN 'DS' WHEN 3 THEN 'NS' END AS TeamC
FROM roster
Result
I.e. For Week 1 TeamA is on R&R, TeamB is on Day Shift and TeamC is on Night Shift.
Suppose we want to get all product categories with total sales greater than 20.
WITH all_sales AS (
SELECT product.price, category.id as category_id, category.description as
category_description
FROM sale
LEFT JOIN product on sale.product_id = product.id
LEFT JOIN category on product.category_id = category.id
)
, sales_by_category AS (
SELECT category_description, sum(price) as total_sales
FROM all_sales
GROUP BY category_id, category_description
)
SELECT * from sales_by_category WHERE total_sales > 20
Suppose we want to query the "cheapest products" from the "top categories".
https://riptutorial.com/ 25
-- all_sales: just a simple SELECT with all the needed JOINS
WITH all_sales AS (
SELECT
product.price as product_price,
category.id as category_id,
category.description as category_description
FROM sale
LEFT JOIN product on sale.product_id = product.id
LEFT JOIN category on product.category_id = category.id
)
-- Group by category
, sales_by_category AS (
SELECT category_id, category_description,
sum(product_price) as total_sales
FROM all_sales
GROUP BY category_id, category_description
)
-- Filtering total_sales > 20
, top_categories AS (
SELECT * from sales_by_category WHERE total_sales > 20
)
-- all_products: just a simple SELECT with all the needed JOINS
, all_products AS (
SELECT
product.id as product_id,
product.description as product_description,
product.price as product_price,
category.id as category_id,
category.description as category_description
FROM product
LEFT JOIN category on product.category_id = category.id
)
-- Order by product price
, cheapest_products AS (
SELECT * from all_products
ORDER by product_price ASC
)
-- Simple inner join
, cheapest_products_from_top_categories AS (
SELECT product_description, product_price
FROM cheapest_products
INNER JOIN top_categories ON cheapest_products.category_id = top_categories.category_id
)
--The main SELECT
SELECT * from cheapest_products_from_top_categories
https://riptutorial.com/ 26
Chapter 9: CREATE Database
Syntax
Examples
CREATE Database
A database is created with the following SQL command:
This would create an empty database named myDatabase where you can create tables.
https://riptutorial.com/ 27
Chapter 10: CREATE FUNCTION
Syntax
Parameters
Argument Description
Remarks
CREATE FUNCTION creates a user-defined function that can be used when doing a SELECT,
INSERT, UPDATE, or DELETE query. The functions can be created to return a single variable or
a single table.
Examples
Create a new Function
END
This example creates a function named FirstWord, that accepts a varchar parameter and returns
another varchar value.
https://riptutorial.com/ 28
Read CREATE FUNCTION online: https://riptutorial.com/sql/topic/2437/create-function
https://riptutorial.com/ 29
Chapter 11: CREATE TABLE
Introduction
The CREATE TABLE statement is used create a new table in the database. A table definition
consists of a list of columns, their types, and any integrity constraints.
Syntax
Parameters
Parameter Details
Contains an 'enumeration' of all the columns that the table have. See Create a
columns
New Table for more details.
Remarks
Table names must be unique.
Examples
Create a New Table
A basic Employees table, containing an ID, and the employee's first and last name along with their
phone number can be created using
);
CREATE TABLE creates a new table in the database, followed by the table name,
Employees
This is then followed by the list of column names and their properties, such as the ID
https://riptutorial.com/ 30
Id int identity(1,1) not null
Value Meaning
states that column will have auto generated values starting at 1 and
identity(1,1)
incrementing by 1 for each new row.
states that all values in this column will have unique values
primary key
You can use any of the other features of a SELECT statement to modify the data before passing it
to the new table. The columns of the new table are automatically created according to the selected
rows.
Duplicate a table
Below you could find the table Employees with a reference to the table Cities.
https://riptutorial.com/ 31
LastName VARCHAR(20) NOT NULL,
PhoneNumber VARCHAR(10) NOT NULL,
CityID INT FOREIGN KEY REFERENCES Cities(CityID)
);
The column CityID of table Employees will reference to the column CityID of table Cities . Below you
could find the syntax to make this.
Value Meaning
REFERENCES
Makes the foreign key (optional)
Cities(CityID)
Makes the reference
to the table Cities column CityID
Important: You couldn't make a reference to a table that not exists in the database. Be source to
make first the table Cities and second the table Employees. If you do it vise versa, it will throw an
error.
Create a Temporary or In-Memory Table
https://riptutorial.com/ 32
SQL Server
To create a temporary table local to the session:
https://riptutorial.com/ 33
Chapter 12: cross apply, outer apply
Examples
CROSS APPLY and OUTER APPLY basics
Apply will be used when when table valued function in the right expression.
create a Department table to hold information about departments. Then create an Employee table
which hold information about the employees. Please note, each employee belongs to a
department, hence the Employee table has referential integrity with the Department table.
First query selects data from Department table and uses CROSS APPLY to evaluate the
Employee table for each record of the Department table. Second query simply joins the
Department table with the Employee table and all the matching records are produced.
SELECT *
FROM Department D
CROSS APPLY (
SELECT *
FROM Employee E
WHERE E.DepartmentID = D.DepartmentID
)A
GO
SELECT *
FROM Department D
INNER JOIN Employee E
ON D.DepartmentID = E.DepartmentID
If you look at the results they produced, it is the exact same result-set; How does it differ from a
JOIN and how does it help in writing more efficient queries.
The first query in Script #2 selects data from Department table and uses OUTER APPLY to
evaluate the Employee table for each record of the Department table. For those rows for which
there is not a match in Employee table, those rows contains NULL values as you can see in case
of row 5 and 6. The second query simply uses a LEFT OUTER JOIN between the Department
table and the Employee table. As expected the query returns all rows from Department table; even
for those rows for which there is no match in the Employee table.
SELECT *
FROM Department D
OUTER APPLY (
SELECT *
FROM Employee E
WHERE E.DepartmentID = D.DepartmentID
)A
GO
SELECT *
FROM Department D
LEFT OUTER JOIN Employee E
ON D.DepartmentID = E.DepartmentID
https://riptutorial.com/ 34
GO
Even though the above two queries return the same information, the execution plan will be bit
different. But cost wise there will be not much difference.
Now comes the time to see where the APPLY operator is really required. In Script #3, I am
creating a table-valued function which accepts DepartmentID as its parameter and returns all the
employees who belong to this department. The next query selects data from Department table and
uses CROSS APPLY to join with the function we created. It passes the DepartmentID for each row
from the outer table expression (in our case Department table) and evaluates the function for each
row similar to a correlated subquery. The next query uses the OUTER APPLY in place of CROSS
APPLY and hence unlike CROSS APPLY which returned only correlated data, the OUTER APPLY
returns non-correlated data as well, placing NULLs into the missing columns.
So now if you are wondering, can we use a simple join in place of the above queries? Then the
answer is NO, if you replace CROSS/OUTER APPLY in the above queries with INNER
JOIN/LEFT OUTER JOIN, specify ON clause (something as 1=1) and run the query, you will get
"The multi-part identifier "D.DepartmentID" could not be bound." error. This is because with JOINs
the execution context of outer query is different from the execution context of the function (or a
derived table), and you can not bind a value/variable from the outer query to the function as a
parameter. Hence the APPLY operator is required for such queries.
Read cross apply, outer apply online: https://riptutorial.com/sql/topic/2516/cross-apply--outer-apply
https://riptutorial.com/ 35
Chapter 13: Data Types
Examples
DECIMAL and NUMERIC
Fixed precision and scale decimal numbers.
Syntax:
DECIMALand NUMERICare functionally equivalent.
Examples:
Integers
Exact-number data types that use integer data.
Data
Range Storage
type
-2^63 (-9,223,372,036,854,775,808) to 2^63-1
bigint 8 Bytes
(9,223,372,036,854,775,807)
https://riptutorial.com/ 36
Data type Range Storage
Syntax:
BINARY [ ( n_bytes ) ]
VARBINARY [ ( n_bytes | max ) ]
Syntax:
CHAR [ ( n_chars ) ]
VARCHAR [ ( n_chars ) ]
Examples:
SELECT CAST('ABC' AS CHAR(10)) -- 'ABC ' (padded with spaces on the right)
SELECT CAST('ABC' AS VARCHAR(10)) -- 'ABC' (no padding due to variable character)
SELECT CAST('ABCDEFGHIJKLMNOPQRSTUVWXYZ' AS CHAR(10)) -- 'ABCDEFGHIJ' (truncated to 10
characters)
Syntax:
NCHAR [ ( n_chars ) ]
NVARCHAR [ ( n_chars | MAX ) ]
Use MAXfor very long strings that may exceed 8000 characters.
https://riptutorial.com/ 37
UNIQUEIDENTIFIER
A 16-byte GUID / UUID.
https://riptutorial.com/ 38
Chapter 14: DELETE
Introduction
The DELETE statement is used to delete records from a table.
Syntax
Examples
DELETE certain rows with WHERE
Omitting a WHERE
clause will delete all rows from a table.
See TRUNCATE documentation for details on how TRUNCATE performance can be better
because it ignores triggers and indexes and logs to just delete the data.
TRUNCATE clause
Use this to reset the table to the condition at which it was created. This deletes all rows and resets
values such as auto-increment. It also doesn't log each individual row deletion.
It is possible to DELETE data from a table if it matches (or mismatches) certain data in other tables.
Let's assume we want to DELETEdata from Source once its loaded into Target.
https://riptutorial.com/ 39
Most common RDBMS implementations (e.g. MySQL, Oracle, PostgresSQL, Teradata) allow
tables to be joined during DELETE allowing more complex comparison in a compact syntax.
Adding complexity to original scenario, let's assume Aggregate is built from Target once a day and
does not contain the same ID but contains the same date. Let us also assume that we want to
delete data from Source only after the aggregate is populated for the day.
In PostgreSQL use:
This essentially results in INNER JOINs between Source, Target and Aggregate. The deletion is
performed on Source when the same IDs exist in Target AND date present in Target for those IDs
also exists in Aggregate.
Same query may also be written (on MySQL, Oracle, Teradata) as:
DELETE Source
FROM Source, TargetSchema.Target, AggregateSchema.Aggregate
WHERE Source.ID = TargetSchema.Target.ID
AND TargetSchema.Target.DataDate = AggregateSchema.Aggregate.AggDate
Explicit joins may be mentioned in Delete statements on some RDBMS implementations (e.g.
Oracle, MySQL) but not supported on all platforms (e.g. Teradata does not support them)
Comparisons can be designed to check mismatch scenarios instead of matching ones with all
syntax styles (observe NOT EXISTS below)
https://riptutorial.com/ 40
Chapter 15: DROP or DELETE Database
Syntax
•MSSQL Syntax:
•DROP DATABASE [ IF EXISTS ] { database_name | database_snapshot_name } [ ,...n ] [;]
•MySQL Syntax:
•DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
Remarks
DROP DATABASE is used for dropping a database from SQL. Be sure to create a backup of your
database before dropping it to prevent accidental loss of information.
Examples
DROP Database
Dropping the database is a simple one-liner statement. Drop database will delete the database,
hence always ensure to have a backup of the database if required.
Below is the command to drop Employees Database
https://riptutorial.com/ 41
Chapter 16: DROP Table
Remarks
DROP TABLE removes the table definition from the schema along with the rows, indexes,
permissions, and triggers.
Examples
Simple drop
MySQL3.19
PostgreSQL8.x
SQL Server2005
SQLite3.0
https://riptutorial.com/ 42
Chapter 17: Example Databases and Tables
Examples
Auto Shop Database
In the following example - Database for an auto shop business, we have a list of departments,
employees, customers and customer cars. We are using foreign keys to create relationships
between the various tables.
Live example: SQL fiddle
Departments
Id Name
1 HR
2 Sales
3 Tech
([Id], [Name])
VALUES
(1, 'HR'),
(2, 'Sales'),
(3, 'Tech')
;
https://riptutorial.com/ 43
Employees
01-01-
1 James Smith 1234567890 NULL 1 1000
2002
23-03-
2 John Johnson 2468101214 1 1 400 2005
12-05-
2009
3 Michael Williams 1357911131 1 2 600
24-07-
2016
4 Johnathon Smith 1212121212 2 1 500
);
INSERT INTO Employees
Customers
https://riptutorial.com/ 44
SQL statements to create the table:
);
INSERT INTO Customers
Cars
2 Mustang WAITING
);
INSERT INTO Cars
https://riptutorial.com/ 45
Library Database
In this example database for a library, we have Authors, Books and BooksAuthors tables.
Authors and Books are known as base tables, since they contain column definition and data for
the actual entities in the relational model. BooksAuthors is known as the relationship table, since
this table defines the relationship between the Books and Authors table.
Authors
(view table)
Id Name Country
3 Jane Austen UK
https://riptutorial.com/ 46
(Name, Country)
VALUES
('J.D. Salinger', 'USA'), ('F. Scott.
Fitzgerald', 'USA'), ('Jane Austen', 'UK'),
('Scott Hanselman', 'USA'), ('Jason N.
Gaylord', 'USA'), ('Pranav Rastogi', 'India'),
('Todd Miranda', 'USA'), ('Christian Wenz',
'USA')
Books
(view table)
Id Title
2 Nine Stories
https://riptutorial.com/ 47
BooksAuthors
(view table)
BookId AuthorId
1 1
2 1
3 1
4 2
5 2
6 3
7 4
7 5
7 6
7 7
7 8
(BookId, AuthorId)
VALUES
(1, 1), (2, 1),
(3, 1), (4,
2), (5, 2),
(6, 3), (7,
4), (7, 5),
(7, 6), (7,
7), (7, 8)
https://riptutorial.com/ 48
Examples
View all authors (view live example):
SELECT
ba.AuthorId,
a.Name AuthorName,
ba.BookId,
b.Title BookTitle
FROM BooksAuthors ba
INNER JOIN Authors a ON a.id = ba.authorid
INNER JOIN Books b ON b.id = ba.bookid
;
Countries Table
In this example, we have a Countries table. A table for countries has many uses, especially in
Financial applications involving currencies and exchange rates.
Live example: SQL fiddle
Some Market data software applications like Bloomberg and Reuters require you to give their API
either a 2 or 3 character country code along with the currency code. Hence this example table has
both the 2-character ISO code column and the 3 character ISO3 code columns.
Countries
(view table)
https://riptutorial.com/ 49
Id ISO ISO3 ISONumeric CountryName Capital ContinentCode CurrencyCode
https://riptutorial.com/ 50
Chapter 18: EXCEPT
Remarks
EXCEPT returns any distinct values from the dataset to the left of the EXCEPT operator that are not
also returned from the right dataset.
Examples
Select dataset except where values are in this other dataset
https://riptutorial.com/ 51
Chapter 19: Execution blocks
Examples
Using BEGIN ... END
BEGIN
UPDATE Employees SET PhoneNumber = '5551234567' WHERE Id = 1;
UPDATE Employees SET Salary = 650 WHERE Id = 3;
END
https://riptutorial.com/ 52
Chapter 20: EXISTS CLAUSE
Examples
EXISTS CLAUSE
Customer Table
Id FirstName LastName
1 Ozgur Ozturk
2 Youssef Medi
3 Henry Tai
Order Table
Id CustomerId Amount
1 2 123.50
2 3 14.80
Result
Id FirstName LastName
2 Youssef Medi
3 Henry Tai
https://riptutorial.com/ 53
Result
Id FirstName LastName
1 Ozgur Ozturk
Purpose
EXISTS, IN and JOIN could sometime be used for the same result, however, they are not equals :
https://riptutorial.com/ 54
Chapter 21: EXPLAIN and DESCRIBE
Examples
DESCRIBE tablename;
are synonyms.
DESCRIBE and EXPLAIN DESCRIBEon a tablename returns the definition of the columns.
DESCRIBE tablename;
Exmple Result:
Here you see the column names, followed by the columns type. It shows if null is allowed in the
column and if the column uses an Index. the default value is also displayed and if the table
contains any special behavior like an auto_increment.
Example result:
on type you see if an index was used. In the column possible_keys you see if the execution plan
can choose from different indexes of if none exists. key tells you the acutal used index. key_len
shows you the size in bytes for one index item. The lower this value is the more index items fit into
the same memory size an they can be faster processed. rows shows you the expected number of
rows the query needs to scan, the lower the better.
Read EXPLAIN and DESCRIBE online: https://riptutorial.com/sql/topic/2928/explain-and-describe
https://riptutorial.com/ 55
Chapter 22: Filter results using WHERE and
HAVING
Syntax
•SELECT column_name
FROM table_name
WHERE column_name operator value
•SELECT column_name, aggregate_function(column_name)
FROM table_name
GROUP BY column_name
HAVING aggregate_function(column_name) operator value
Examples
The WHERE clause only returns rows that match its criteria
Steam has a games under $10 section of their store page. Somewhere deep in the heart of their
systems, there's probably a query that looks something like:
SELECT *
FROM Items
WHERE Price < 10
This example uses the Car Table from the Example Databases.
SELECT *
FROM Cars
WHERE TotalCost IN (100, 200, 300)
This query will return Car #2 which costs 200 and Car #3 which costs 100. Note that this is
equivalent to using multiple clauses with OR, e.g.:
SELECT *
FROM Cars
WHERE TotalCost = 100 OR TotalCost = 200 OR TotalCost = 300
This example uses the Employees Table from the Example Databases.
https://riptutorial.com/ 56
SELECT *
FROM Employees
WHERE FName LIKE 'John'
This query will only return Employee #1 whose first name matches 'John' exactly.
SELECT *
FROM Employees
WHERE FName like 'John%'
• John%- will return any Employee whose name begins with 'John', followed by any amount of
characters
•
%John- will return any Employee whose name ends with 'John', proceeded by any amount of
• characters
%John%- will return any Employee whose name contains 'John' anywhere within the value
In this case, the query will return Employee #2 whose name is 'John' as well as Employee #4
whose name is 'Johnathon'.
WHERE clause with NULL/NOT NULL values
SELECT *
FROM Employees
WHERE ManagerId IS NULL
This statement will return all Employee records where the value of the ManagerId column is NULL.
SELECT *
FROM Employees
WHERE ManagerId IS NOT NULL
This statement will return all Employee records where the value of the ManagerId is not NULL.
Note: The same query will not return results if you change the WHERE clause to WHERE ManagerId
= NULL or WHERE ManagerId <> NULL.
https://riptutorial.com/
57
Use HAVING with Aggregate Functions
Unlike the WHERE clause, HAVING can be used with aggregate functions.
An aggregate function is a function where the values of multiple rows are grouped
together as input on certain criteria to form a single value of more significant meaning
or measurement (Wikipedia).
This example uses the Car Table from the Example Databases.
This query will return the CustomerId and Number of Cars count of any customer who has more than
one car. In this case, the only customer who has more than one car is Customer #1.
The results will look like:
1 2
This query will return all ItemSales records that have a quantity that is greater or equal to 10 and
less than or equal to 17. The results will look like:
https://riptutorial.com/ 58
Using the BETWEEN operator with Date Values:
This query will return all ItemSales records with a SaleDate that is greater than or equal to July 11,
2013 and less than or equal to May 24, 2013.
When comparing datetime values instead of dates, you may need to convert the
datetime values into a date values, or add or subtract 24 hours to get the correct
results.
This query will return all customers whose name alphabetically falls between the letters 'D' and 'L'.
In this case, Customer #1 and #3 will be returned. Customer #2, whose name begins with a 'M' will
not be included.
Id FName LName
1 William Jones
3 Richard Davis
Equality
This statement will return all the rows from the tableEmployees.
https://riptutorial.com/ 59
2 John Johnson 2468101214 1 1 12 400 23-03-2005 23-03-
2005 01-01-2002 2 1 600 12-05-2009 12-05-
3 Michael Williams 1357911131 500 24-07-2016 24-07-
2009 NULL 1212121212
4 Johnathon Smith
2016 01-01-2002
Using a WHEREat the end of your SELECT statement allows you to limit the returned rows to a
condition. In this case, where there is an exact match using the sign:
=
AND and OR
You can also combine several operators together to create more complex WHERE conditions. The
following examples use the Employees table:
AND
Will return:
OR
https://riptutorial.com/ 60
SELECT * FROM Employees WHERE DepartmentId = 2 OR ManagerId = 2
Will return:
Orders Table
1 2 5 100
1 3 2 200
1 4 1 500
2 1 4 50
3 5 6 700
To check for customers who have ordered both - ProductID 2 and 3, HAVING can be used
select customerId
from orders
where productID in (2,3)
group by customerId
having count(distinct productID) = 2
Return value:
customerId
The query selects only records with the productIDs in questions and with the HAVING clause
checks for groups having 2 productIds and not just one.
Another possibility would be
select customerId
from orders
group by customerId
having sum(case when productID = 2 then 1 else 0 end) > 0
https://riptutorial.com/ 61
and sum(case when productID = 3 then 1 else 0 end) > 0
This query selects only groups having at least one record with productID 2 and at least one with
productID 3.
Where EXISTS
https://riptutorial.com/ 62
Chapter 23: Finding Duplicates on a Column
Subset with Detail
Remarks
•To select rows with out duplicates change the WHERE clause to "RowCnt = 1"
•To select one row from each set use Rank() instead of Sum() and change the outer WHERE
clause to select rows with Rank() = 1
Examples
Students with same name and date of birth
This example uses a Common Table Expression and a Window Function to show all duplicate
rows (on a subset of columns) side by side.
Read Finding Duplicates on a Column Subset with Detail online:
https://riptutorial.com/sql/topic/1585/finding-duplicates-on-a-column-subset-with-detail
https://riptutorial.com/ 63
Chapter 24: Foreign Keys
Examples
Creating a table with a foreign key
In this example we have an existing table, SuperHeros.
We will add a new table in order to store the powers of each super hero:
The following table will contain the information of the subjects offered by the Computer science
branch:
https://riptutorial.com/ 64
(The data type of the Foreign Key must match the datatype of the referenced key.)
The Foreign Key constraint on the column Dept_Code allows values only if they already exist in the
referenced table, Department. This means that if you try to insert the following values:
the database will raise a Foreign Key violation error, because CS300 does not exist in the
Department
https://riptutorial.com/ 65
Chapter 25: Functions (Aggregate)
Syntax
Remarks
In database management an aggregate function is a function where the values of multiple rows
are grouped together as input on certain criteria to form a single value of more significant meaning
or measurement such as a set, a bag or a list.
MIN MAX returns the smallest value in a given column returns the largest value in a given column
SUM AVG returns the sum of the numeric values in a given column returns the average value of a
COUNT given column returns the total number of values in a given column returns the number of
COUNT(*) rows in a table Is a column or an expression that contains a column in a GROUP BY clause.
GROUPIN returns the statistical standard deviation of all values in the specified
G STDEV
expression.
STDEVP returns the statistical standard deviation for the population for all values in the
specified expression.
VAR returns the statistical variance of all values in the specified expression. may be
followed by the OVER clause.
VARP returns the statistical variance for the population for all values in the specified
expression.
Aggregate functions are used to compute against a "returned column of numeric data"
from your SELECT statement. They basically summarize the results of a particular
column of selected data. - SQLCourse2.com
https://riptutorial.com/ 66
Examples
SUM
Sum function sum the value of all the rows in the group. If the group by clause is omitted then sums
all the rows.
TotalSalary
2500
DepartmentI TotalSalary
d12 2000
500
Conditional aggregation
Payments Table
John Debit
select customer,
sum(case when payment_type = 'credit' then amount else 0 end) as credit,
sum(case when payment_type = 'debit' then amount else 0 end) as debit
from payments
group by customer
Result:
https://riptutorial.com/ 67
Customer Credit Debit
Peter 400 0
select customer,
sum(case when payment_type = 'credit' then 1 else 0 end) as credit_transaction_count,
sum(case when payment_type = 'debit' then 1 else 0 end) as debit_transaction_count
from payments
group by customer
Result:
Peter 21 01
John
AVG()
The aggregate function AVG() returns the average of a given expression, usually numeric values
in a column. Assume we have a table containing the yearly calculation of population in cities
across the world. The records for New York City look similar to the ones below:
EXAMPLE TABLE
To select the average population of the New York City, USA from a table containing city names,
population measurements, and measurement years for last ten years:
QUERY
Notice how measurement year is absent from the query since population is being averaged over
time.
https://riptutorial.com/ 68
RESULTS
city_name avg_population
Note: The AVG() function will convert values to numeric types. This is especially
important to keep in mind when working with dates.
List Concatenation
List Concatenation aggregates a column or expression by combining the values into a single string
for each group. A string to delimit each value (either blank or a comma when omitted) and the
order of the values in the result can be specified. While it is not part of the SQL standard, every
major relational database vendor supports it in their own way.
MySQL
SELECT ColumnA
, GROUP_CONCAT(ColumnB ORDER BY ColumnB SEPARATOR ',') AS ColumnBs
FROM TableName
GROUP BY ColumnA
ORDER BY ColumnA;
PostgreSQL
SELECT ColumnA
, STRING_AGG(ColumnB, ',' ORDER BY ColumnB) AS ColumnBs
FROM TableName
GROUP BY ColumnA
ORDER BY ColumnA;
SQL Server
https://riptutorial.com/ 69
SQL Server 2016 and earlier
(CTE included to encourage the DRY principle)
WITH CTE_TableName AS (
SELECT ColumnA, ColumnB
FROM TableName)
SELECT t0.ColumnA
, STUFF((
SELECT ',' + t1.ColumnB
FROM CTE_TableName t1
WHERE t1.ColumnA = t0.ColumnA
ORDER BY t1.ColumnB
FOR XML PATH('')), 1, 1, '') AS ColumnBs
FROM CTE_TableName t0
GROUP BY t0.ColumnA
ORDER BY ColumnA;
SQLite
without ordering:
SELECT ColumnA
, GROUP_CONCAT(ColumnB, ',') AS ColumnBs
FROM TableName
GROUP BY ColumnA
ORDER BY ColumnA;
WITH CTE_TableName AS (
SELECT ColumnA, ColumnB
FROM TableName
ORDER BY ColumnA, ColumnB)
SELECT ColumnA
, GROUP_CONCAT(ColumnB, ',') AS ColumnBs
FROM CTE_TableName
GROUP BY
ColumnA ORDER BY
ColumnA;
Count
https://riptutorial.com/ 70
You can count the number of rows:
TotalRows
DepartmentId NumEmployees
1 3
2 1
You can count over a column/expression with the effect that will not count the NULLvalues:
mgr
You can also use DISTINCT inside of another function such as COUNT to only find the DISTINCT
members of the set to perform the operation on.
For example:
Will return different values. The SingleCount will only Count individual Continents once, while the
AllCount will include duplicates.
ContinentCode
OC
https://riptutorial.com/ 71
ContinentCode
EU AS NA NA AF
AF
AllCount: 7 SingleCount: 5
Max
Find the maximum value of column:
Above example will return largest value for column age of employee table.
Syntax:
Min
Above example will return smallest value for column age of employee table.
Syntax:
https://riptutorial.com/ 72
Chapter 26: Functions (Analytic)
Introduction
You use analytic functions to determine values based on groups of values. For example, you can
use this type of function to determine running totals, percentages, or the top result within a group.
Syntax
Examples
FIRST_VALUE
You use the FIRST_VALUE function to determine the first value in an ordered result set, which you
identify using a scalar expression.
In this example, the FIRST_VALUE function is used to return the ID of the state or province with the
lowest tax rate. The OVERclause is used to order the tax rates to obtain the lowest rate.
https://riptutorial.com/ 73
StateProvinceID Name TaxRate FirstValue
6
LAST_VALUE
3
The LAST_VALUE function provides the last value in an ordered result set, which you specify using a
scalar expression.
This example uses the LAST_VALUEfunction to return the last value for each rowset in the ordered
values.
The LAG function provides data on rows before the current row in the same result set. For example,
in a SELECT statement, you can compare values in the current row with values in a previous row.
You use a scalar expression to specify the values that should be compared. The offset parameter
is the number of rows before the current row that will be used in the comparison. If you don't
specify the number of rows, the default value of one row is used.
The default parameter specifies the value that should be returned when the expression at offset
has a NULL value. If you don't specify a value, a value of NULL is returned.
The LEAD function provides data on rows after the current row in the row set. For example, in a
https://riptutorial.com/ 74
SELECT statement, you can compare values in the current row with values in the following row.
You specify the values that should be compared using a scalar expression. The offset parameter
is the number of rows after the current row that will be used in the comparison.
You specify the value that should be returned when the expression at offset has a NULL value using
the default parameter. If you don't specify these parameters, the default of one row is used and a
value of NULLis returned.
This example uses the LEAD and LAG functions to compare the sales values for each employee
to date with those of the employees listed above and below, with records ordered based on the
BusinessEntityID column.
The PERCENT_RANK function calculates the ranking of a row relative to the row set. The percentage is
based on the number of rows in the group that have a lower value than the current row.
The first value in the result set always has a percent rank of zero. The value for the highest-ranked
– or last – value in the set is always one.
The CUME_DIST function calculates the relative position of a specified value in a group of values, by
determining the percentage of values less than or equal to that value. This is called the cumulative
distribution.
https://riptutorial.com/ 75
FROM Employee;
In this example, you use an ORDER clause to partition – or group – the rows retrieved by the SELECT
statement based on employees' job titles, with the results in each group sorted based on the
numbers of sick leave hours that employees have used.
Cumulative
BusinessEntityID JobTitle SickLeaveHours Percent Rank
Distribution
Application
267 57 0 0.25
Specialist
Application
268 56 0.333333333333333 0.75
Specialist
Application
269 Specialist 56 0.333333333333333 0.75
Application
272 Specialist 55 1 1
Assitant to
the Cheif
Financial
262 Officer 48 0 1
Benefits
Specialist
239 Buyer 45 0 1
The PERCENT_RANK function ranks the entries within each group. For each entry, it returns the
percentage of entries in the same group that have lower values.
The CUME_DIST function is similar, except that it returns the percentage of values less than or equal
to the current value.
PERCENTILE_DISC and PERCENTILE_CONT
The PERCENTILE_DISCfunction lists the value of the first entry where the cumulative distribution is
https://riptutorial.com/ 76
higher than the percentile that you provide using the numeric_literal parameter.
The values are grouped by rowset or partition, as specified by the WITHIN GROUP clause.
The PERCENTILE_CONT function is similar to the PERCENTILE_DISC function, but returns the average of
the sum of the first matching entry and the next entry.
To find the exact value from the row that matches or exceeds the 0.5 percentile, you pass the
percentile as the numeric literal in the PERCENTILE_DISC function. The Percentile Discreet column in
a result set lists the value of the row at which the cumulative distribution is higher than the
specified percentile.
Cumulative Percentile
BusinessEntityID JobTitle SickLeaveHours
Distribution Discreet
Application
272 55 0.25 56
Specialist
Application
268 56 0.75 56
Specialist
Application
269 Specialist 56 0.75 56
Application
267 Specialist 57 1 56
To base the calculation on a set of values, you use the PERCENTILE_CONT function. The "Percentile
Continuous" column in the results lists the average value of the sum of the result value and the
next highest matching value.
https://riptutorial.com/ 77
Cumulative Percentile Percentile
BusinessEntityID JobTitle SickLeaveHours Distribution
Discreet Continuous
Application
272 55 0.25 56 56
Specialist
Application
268 56 0.75 56 56
Specialist
Application
269 Specialist 56 0.75 56 56
Application
267 Specialist 57 1 56 56
https://riptutorial.com/ 78
Chapter 27: Functions (Scalar/Single Row)
Introduction
SQL provides several built-in scalar functions. Each scalar function takes one value as input and
returns one value as output for each row in a result set.
You use scalar functions wherever an expression is allowed within a T-SQL statement.
Syntax
Remarks
Scalar or Single-Row functions are used to operate each row of data in the result set, as opposed
to aggregate functions which operate on the entire result set.
There are ten types of scalar functions.
1. Configuration functions provide information about the configuration of the current SQL
instance.
2. Conversion functions convert data into the correct data type for a given operation. For
example, these types of functions can reformat information by converting a string to a date or
number to allow two different types to be compared.
3. Date and time functions manipulate fields containing date and time values. They can return
numeric, date, or string values. For example, you can use a function to retrieve the current
day of the week or year or to retrieve only the year from the date.
The values returned by date and time functions depend on the date and time set for the operating
system of the computer running the SQL instance.
4. Logical function that performs operations using logical operators. It evaluates a set of
conditions and returns a single result.
5. Mathematical functions perform mathematical operations, or calculations, on numeric
https://riptutorial.com/ 79
expressions. This type of function returns a single numeric value.
6. Metadata functions retrieve information about a specified database, such as its name and
database objects.
7. Security functions provide information that you can use to manage the security of a
database, such as information about database users and roles.
8. String functions perform operations on string values and return either numeric or string
values.
Using string functions, you can, for example, combine data, extract a substring, compare strings,
or convert a string to all uppercase or lowercase characters.
9. System functions perform operations and return information about values, objects, and
settings for the current SQL instance
10. System statistical functions provide various statistics about the current SQL instance – for
example, so that you can monitor the system's current performance levels.
Examples
Character modifications
Character modifying functions include converting characters to upper or lower case characters,
converting numbers to formatted numbers, performing character manipulation, etc.
The lower(char) function converts the given character parameter to be lower-cased characters.
would return the customer's last name changed from "SMITH" to "smith".
Date And Time
In SQL, you use date and time data types to store calendar information. These data types include
the time, date, smalldatetime, datetime, datetime2, and datetimeoffset. Each data type has a
specific format.
smalldatetime YYYY-MM-DD
https://riptutorial.com/ 80
The function returns the name or value of a specific part of the date.
DATENAME
Datename
Saturday
You use the GETDATE function to determine the current date and time of the computer running the
current SQL instance. This function doesn't include the time zone difference.
Systemdate
2017-01-14 11:11:47.7230728
In the syntax, datepart is the parameter that specifies which part of the date you want to use to
calculate difference. The datepart can be year, month, week, day, hour, minute, second, or
millisecond. You then specify the start date in the startdate parameter and the end date in the
enddate parameter for which you want to find the difference.
43659 43660 7 7 7 7
43661 43662
Added20MoreDays
2017-02-03 00:00:00.000
https://riptutorial.com/ 81
Configuration and Conversion Function
An example of a configuration function in SQL is the
the name of the local server that's running SQL. function. This function provides
@@SERVERNAME
Server
SQL064
In SQL, most data conversions occur implicitly, without any user intervention.
To perform any conversions that can't be completed implicitly, you can use the CAST or CONVERT
functions.
The CAST function syntax is simpler than the CONVERT function syntax, but is limited in what it can do.
In here, we use both the CAST and CONVERT functions to convert the datetime data type to the varchar
data type.
The CAST function always uses the default style setting. For example, it will represent dates and
times using the format YYYY-MM-DD.
The CONVERT function uses the date and time style you specify. In this case, 3 specifies the date
format dd/mm/yy.
USE AdventureWorks2012
GO
SELECT FirstName + ' ' + LastName + ' was hired on ' +
CAST(HireDate AS varchar(20)) AS 'Cast',
FirstName + ' ' + LastName + ' was hired on ' +
CONVERT(varchar, HireDate, 3) AS 'Convert'
FROM Person.Person AS p
JOIN HumanResources.Employee AS e
ON p.BusinessEntityID = e.BusinessEntityID
GO
Cast Convert
David Hamiltion was hired on 2003-02-04 David Hamiltion was hired on 04/02/03
Another example of a conversion function is the PARSE function. This function converts a string to a
specified data type.
In the syntax for the function, you specify the string that must be converted, the AS keyword, and
then the required data type. Optionally, you can also specify the culture in which the string value
should be formatted. If you don't specify this, the language for the session is used.
https://riptutorial.com/ 82
If the string value can't be converted to a numeric, date, or time format, it will result in an error.
You'll then need to use CAST or CONVERTfor the conversion.
Date in English
2012-08-13 00:00:00.0000000
Result
Sales
In this example, you use the CHOOSE function to return the second entry in a list of departments.
The IIF function returns one of two values, based on a particular condition. If the condition is true,
it will return true value. Otherwise it will return a false value.
In the syntax, the boolean_expression parameter specifies the Boolean expression. The
true_value parameter specifies the value that should be returned if the boolean_expression
evaluates to true and the false_value parameter specifies the value that should be returned if the
boolean_expression evaluates to false.
3763178.1787 Bonus No
172524.4512 Bonus
https://riptutorial.com/ 83
In this example, you use the IIF function to return one of two values. If a sales person's year-to-
date sales are above 200,000, this person will be eligible for a bonus. Values below 200,000 mean
that employees don't qualify for bonuses.
One example is the SIGN function, which returns a value indicating the sign of an expression. The
value of -1 indicates a negative expression, the value of +1 indicates a positive expression, and 0
indicates zero.
Sign
-1
In the example, the input is a negative number, so the Results pane lists the result -1.
Another mathematical function is the POWER function. This function provides the value of an
expression raised to a specified power.
In the syntax, the float_expression parameter specifies the expression, and the y parameter
specifies the power to which you want to raise the expression.
Result
125000
https://riptutorial.com/ 84
Chapter 28: GRANT and REVOKE
Syntax
Remarks
Grant permissions to users. If the WITH GRANT OPTION is specified, the grantee additionally gains the
privilege to grant the given permission or revoke previously granted permissions.
Examples
Grant/revoke privileges
Revoke from User1 and User2 the permission to perform SELECT and UPDATE operations on table
Employees.
Read GRANT and REVOKE online: https://riptutorial.com/sql/topic/5574/grant-and-revoke
https://riptutorial.com/ 85
Chapter 29: GROUP BY
Introduction
Results of a SELECT query can be grouped by one or more columns using the GROUP BY
statement: all results with the same value in the grouped columns are aggregated together. This
generates a table of partial results, instead of one result. GROUP BY can be used in conjunction
with aggregation functions using the HAVING statement to define how non-grouped columns are
aggregated.
Syntax
•GROUP BY {
column-expression
| ROLLUP ( <group_by_expression> [ ,...n ] )
| CUBE ( <group_by_expression> [ ,...n ] )
| GROUPING SETS ( [ ,...n ] )
| () --calculates the grand total
} [ ,...n ]
• <group_by_expression> ::=
column-expression
| ( column-expression [ ,...n ] )
• <grouping_set> ::=
() --calculates the grand total
| <grouping_set_item>
| ( <grouping_set_item> [ ,...n ] )
•<grouping_set_item> ::=
<group_by_expression>
| ROLLUP ( <group_by_expression> [ ,...n ] )
| CUBE ( <group_by_expression> [ ,...n ] )
Examples
USE GROUP BY to COUNT the number of rows for each unique entry in a
given column
Let's say you want to generate counts or subtotals for a given value in a column.
https://riptutorial.com/ 86
Name
GreatHouseAllegience
Arya
Stark
Cercei
Lannister
Myrcella Lannister
Yara Greyjoy
Catelyn Stark
Sansa Stark
Without GROUP BY, COUNT will simply return a total number of rows:
returns...
Number_of_Westerosians
But by adding GROUP BY, we can COUNT the users for each value in a given column, to return
the number of people in a given Great House, say:
returns...
House Number_of_Westerosians
Stark 3
Greyjoy 1
Lannister 2
It's common to combine GROUP BY with ORDER BY to sort results by largest or smallest
category:
https://riptutorial.com/ 87
returns...
House Number_of_Westerosians
Stark 321
Lannister
Greyjoy
A HAVING clause filters the results of a GROUP BY expression. Note: The following examples are
using the Library example database.
Examples:
Return all authors that wrote more than one book (live example).
SELECT
a.Id,
a.Name,
COUNT(*) BooksWritten
FROM BooksAuthors ba
INNER JOIN Authors a ON a.id = ba.authorid
GROUP BY
a.Id,
a.Name
HAVING COUNT(*) > 1 -- equals to HAVING BooksWritten > 1
;
Return all books that have more than three authors (live example).
SELECT
b.Id,
b.Title,
COUNT(*) NumberOfAuthors
FROM BooksAuthors ba
INNER JOIN Books b ON b.id = ba.bookid
GROUP BY
b.Id,
b.Title
HAVING COUNT(*) > 3 -- equals to HAVING NumberOfAuthors > 3
;
It might be easier if you think of GROUP BY as "for each" for the sake of explanation. The query
below:
https://riptutorial.com/ 88
GROUP BY EmpID
is saying:
+-----+-------------+
|EmpID|MonthlySalary| +--
---+-------------+ |1 |200 | +---
--+-------------+ |2 |300 | +----
-+-------------+
Result:
+-+---+
|1|200| +-
+---+
|2|300| +-
+---+
Sum wouldn't appear to do anything because the sum of one number is that number. On the other
hand if it looked like this:
+-----+-------------+
|EmpID|MonthlySalary| +--
---+-------------+ |1 |200 | +---
--+-------------+ |1 |300 | +----
-+-------------+ |2 |300 | +-----
+-------------+
Result:
+-+---+
|1|500| +-
+---+
|2|300| +-
+---+
Then it would because there are two EmpID 1's to sum together.
ROLAP aggregation (Data Mining)
Description
The SQL standard provides two additional aggregate operators. These use the polymorphic value
https://riptutorial.com/ 89
"ALL" to denote the set of all values that an attribute can take. The two operators are:
•with data cube that it provides all possible combinations than the argument attributes of the
clause.
• with roll up that it provides the aggregates obtained by considering the attributes in order
from left to right compared how they are listed in the argument of the clause.
Examples
With cube
select Food,Brand,Total_amount
from Table
group by Food,Brand,Total_amount with cube
Pizza Brand2
Pizza ALL
ALL Brand1
ALL Brand2
ALL ALL
With roll up
https://riptutorial.com/ 90
select Food,Brand,Total_amount
from Table
group by Food,Brand,Total_amount with roll up
Pizza Brand2
Pizza ALL
ALL
https://riptutorial.com/ 91
Chapter 30: Identifier
Introduction
This topic is about identifiers, i.e. syntax rules for names of tables, columns, and other database
objects.
Where appropriate, the examples should cover variations used by different SQL implementations,
or identify the SQL implementation of the example.
Examples
Unquoted identifiers
Unquoted identifiers can use letters (a-z), digits (0-9), and underscore (_), and must start with a
letter.
Depending on SQL implementation, and/or database settings, other characters may be allowed,
some even as the first character, e.g.
Unquoted identifiers are case-insensitive. How this is handled depends greatly on SQL
implementation:
•MS SQL: Case-preserving, sensitivity defined by database character set, so can be case-
sensitive.
https://riptutorial.com/ 92
Chapter 31: IN clause
Examples
Simple IN clause
To get records having any of the given
ids
select *
from products
where id in (1,8,3)
select *
from products
where id = 1
or id = 8
or id = 3
SELECT *
FROM customers
WHERE id IN (
SELECT DISTINCT customer_id
FROM orders
);
The above will give you all the customers that have orders in the system.
https://riptutorial.com/ 93
Chapter 32: Indexes
Introduction
Indexes are a data structure that contains pointers to the contents of a table arranged in a specific
order, to help the database optimize queries. They are similar to the index of book, where the
pages (rows of the table) are indexed by their page number.
Several types of indexes exist, and can be created on a table. When an index exists on the
columns used in a query's WHERE clause, JOIN clause, or ORDER BY clause, it can substantially
improve query performance.
Remarks
Indexes are a way of speeding up read queries by sorting the rows of a table according to a
column.
The effect of an index is not noticeable for small databases like the example, but if there are a
large number of rows, it can greatly improve performance. Instead of checking every row of the
table, the server can do a binary search on the index.
The tradeoff for creating an index is write speed and database size. Storing the index takes space.
Also, every time an INSERT is done or the column is updated, the index must be updated. This is
not as expensive an operation as scanning the entire table on a SELECT query, but it is still
something to keep in mind.
Examples
Creating an Index
This will create an index for the column EmployeeId in the table Cars. This index will improve the
speed of queries asking the server to sort or select by values in EmployeeId, such as the
following:
In this case, the index would be useful for queries asking to sort or select by all included columns,
if the set of conditions is ordered in the same way. That means that when retrieving the data, it can
https://riptutorial.com/ 94
find the rows to retrieve using the index, instead of looking through the full table.
For example, the following case would utilize the second index;
If the order differs, however, the index does not have the same advantages, as in the following;
The index is not as helpful because the database must retrieve the entire index, across all values
of EmployeeId and CarID, in order to find which items have OwnerId = 17.
(The index may still be used; it may be the case that the query optimizer finds that retrieving the
index and filtering on the OwnerId, then retrieving only the needed rows is faster than retrieving the
full table, especially if the table is large.)
Clustered, Unique, and Sorted Indexes
Indexes can have several characteristics that can be set either at creation, or by altering existing
indexes.
The above SQL statement creates a new clustered index on Employees. Clustered indexes are
indexes that dictate the actual structure of the table; the table itself is sorted to match the structure
of the index. That means there can be at most one clustered index on a table. If a clustered index
already exists on the table, the above statement will fail. (Tables with no clustered indexes are
also called heaps.)
This will create an unique index for the column Email in the table Customers. This index, along
with speeding up queries like a normal index, will also force every email address in that column to
be unique. If a row is inserted or updated with a non-unique Email value, the insertion or update
will, by default, fail.
This creates an index on Customers which also creates a table constraint that the EmployeeID
must be unique. (This will fail if the column is not currently unique - in this case, if there are
employees who share an ID.)
This creates an index that is sorted in descending order. By default, indexes (in MSSQL server, at
least) are ascending, but that can be changed.
https://riptutorial.com/ 95
Inserting with a Unique Index
This will fail if an unique index is set on the Email column of Customers. However, alternate
behavior can be defined for this case:
Syntax:
Example:
Sorted Index
If you use an index that is sorted the way you would retrieve it, the
additional sorting when in retrieval. SELECT statement would not do
The database system would not do additional sorting, since it can do an index-lookup in that order.
We can use command DROPto delete our index. In this example we will DROP the index called
ix_cars_employee_id on the table Cars.
This deletes the index entirely, and if the index is clustered, will remove any clustering. It cannot
be rebuilt without recreating the index, which can be slow and computationally expensive. As an
alternative, the index can be disabled:
https://riptutorial.com/ 96
This allows the table to retain the structure, along with the metadata about the index.
Critically, this retains the index statistics, so that it is possible to easily evaluate the change. If
warranted, the index can then later be rebuilt, instead of being recreated completely;
This schema allows for a 0..1 relationship - people can have zero or one driving licenses and each
license can only belong to one person
Rebuild index
Over the course of time B-Tree indexes may become fragmented because of
updating/deleting/inserting data. In SQLServer terminology we can have internal (index page
which is half empty ) and external (logical page order doesn't correspond physical order).
Rebuilding index is very similar to dropping and re-creating it.
We can re-build an index with
By default rebuilding index is offline operation which locks the table and prevents DML against it ,
but many RDBMS allow online rebuilding. Also, some DB vendors offer alternatives to index
rebuilding such as REORGANIZE (SQLServer) or COALESCE/SHRINK SPACE(Oracle).
Clustered index
When using clustered index, the rows of the table are sorted by the column to which the clustered
index is applied. Therefore, there can be only one clustered index on the table because you can't
order the table by two different columns.
Generally, it is best to use clustered index when performing reads on big data tables. The
donwside of clustered index is when writing to table and data need to be reorganized (resorted).
An example of creating a clustered index on a table Employees on column Employee_Surname:
Nonclustered indexes are stored separately from the table. Each index in this structure contains a
https://riptutorial.com/ 97
pointer to the row in the table which it represents.
This pointers are called a row locators. The structure of the row locator depends on whether the
data pages are stored in a heap or a clustered table. For a heap, a row locator is a pointer to the
row. For a clustered table, the row locator is the clustered index key.
There can be multiple nonclustered indexes on the table. The read operations are generally slower
with non clustered indexes than with clustered indexes as you have to go first to index and than to
the table. There are no restrictions in write operations however.
Partial or Filtered Index
SQL Server and SQLite allow to create indexes that contain not only a subset of columns, but also
a subset of rows.
Consider a constant growing amount of orders with order_state_id equal to finished (2), and a
stable amount of orders with order_state_id equal to started (1).
If your business make use of queries like this:
Partial indexing allows you to limit the index, including only the unfinished orders:
This index will be smaller than an unfiltered index, which saves space and reduces the cost of
updating the index.
Read Indexes online: https://riptutorial.com/sql/topic/344/indexes
https://riptutorial.com/ 98
Chapter 33: Information Schema
Examples
Basic Information Schema Search
One of the most useful queries for end users of large RDBMS's is a search of an information
schema.
Such a query allows users to rapidly find database tables containing columns of interest, such as
when attempting to relate data from 2 tables indirectly through a third table, without existing
knowledge of which tables may contain keys or other useful columns in common with the target
tables.
Using T-SQL for this example, a database's information schema may be searched as follows:
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%Institution%'
The result contains a list of matching columns, their tables' names, and other useful information.
https://riptutorial.com/ 99
Chapter 34: INSERT
Syntax
Examples
Insert New Row
This statement will insert a new row into the Customers table. Note that a value was not specified
for the Id column, as it will be added automatically. However, all other column values must be
specified.
Insert Only Specified Columns
This statement will insert a new row into the Customers table. Data will only be inserted into the
columns specified - note that no value was provided for the PhoneNumbercolumn. Note, however,
that all columns marked as not null must be included.
INSERT data from another table using SELECT
This example will insert all Employees into the Customers table. Since the two tables have different
fields and you don't want to move all the fields over, you need to set which fields to insert into and
which fields to select. The correlating field names don't need to be called the same thing, but then
need to be the same data type. This example is assuming that the Id field has an Identity
Specification set and will auto increment.
If you have two tables that have exactly the same field names and just want to move all the
records over you can use:
https://riptutorial.com/ 100
Insert multiple rows at once
Multiple rows can be inserted with a single insert command:
INSERT INTO tbl_name (field1, field2, field3)
For inserting large quantities of data (bulk insert) at the same time, DBMS-specific features and
recommendations exist.
MySQL - LOAD DATA INFILE
https://riptutorial.com/ 101
Chapter 35: JOIN
Introduction
JOIN is a method of combining (joining) information from two tables. The result is a stitched set of
columns from both tables, defined by the join type (INNER/OUTER/CROSS and
LEFT/RIGHT/FULL, explained below) and join criteria (how rows from both tables relate).
A table may be joined to itself or to any other table. If information from more than two tables needs
to be accessed, multiple joins can be specified in a FROM clause.
Syntax
Remarks
Joins, as their name suggests, are a way of querying data from several tables in a joint fashion,
with the rows displaying columns taken from more than one table.
Examples
Basic explicit inner join
A basic join (also called "inner join") queries data from two tables, with their relationship defined in
a join clause.
The following example will select employees' first names (FName) from the Employees table and
the name of the department they work for (Name) from the Departments table:
Employees.FName Departments.Name
James HR
John HR
Richard Sales
https://riptutorial.com/ 102
Implicit Join
Joins can also be performed by having several tables in the from clause, separated with commas ,
and defining the relationship between them in the where clause. This technique is called an Implicit
Join (since it doesn't actually contain a join clause).
All RDBMSs support it, but the syntax is usually advised against. The reasons why it is a bad idea
to use this syntax are:
•It is possible to get accidental cross joins which then return incorrect results, especially if you
have a lot of joins in the query.
•If you intended a cross join, then it is not clear from the syntax (write out CROSS JOIN
instead), and someone is likely to change it during maintenance.
The following example will select employee's first names and the name of the departments they
work for:
e.FName d.Name
James HR
John HR
Richard Sales
https://riptutorial.com/ 103
Departments.Name Employees.FName
HR James
HR John
HR Johnathon
Sales Michael
Tech NULL
01-01-
1 James Smith 1234567890 NULL 1 1000
2002
23-03-
2 John Johnson 2468101214 1 1 400 2005
12-05-
3 Michael Williams 1357911131 1 2 600 2009
24-07-
and
Id Name
1 HR
2 Sales
3 Tech
First a Cartesian product is created from the two tables giving an intermediate table.
The records that meet the join criteria (Departments.Id = Employees.DepartmentId) are
highlighted in bold; these are passed to the next stage of the query.
As this is a LEFT OUTER JOIN all records are returned from the LEFT side of the join
(Departments), while any records on the RIGHT side are given a NULL marker if they do not
match the join criteria. In the table below this will return Tech with NULL
https://riptutorial.com/ 104
Id Name Id FName LName PhoneNumber ManagerId DepartmentId Salary Hir
01-
1 HR 1 James Smith 1234567890 NULL 1 1000
200
23-
1 HR 2 John Johnson 2468101214 1 1 400
200
12-
1 HR 3 Michael Williams 1357911131 1 2 600 200
24-
201
1 HR 4 Johnathon Smith 1212121212 2 1 500
01-
200
2 Sales 1 James Smith 1234567890 NULL 1 1000 23-
200
2 Sales 2 John Johnson 2468101214 1 1 400 12-
200
24-
2 Sales 3 Michael Williams 1357911131 1 2 600 201
01-
2 Sales 4 Johnathon Smith 1212121212 2 1 500 200
23-
200
3 Tech 1 James Smith 1234567890 NULL 1 1000 12-
200
3 Tech 2 John Johnson 2468101214 1 1 400 24-
201
Finally each expression used within the SELECT clause is evaluated to return our final table:
Departments.Name Employees.FName
HR James
HR John
Sales Richard
Tech NULL
https://riptutorial.com/ 105
Self Join
A table may be joined to itself, with different rows matching each other by some condition. In this
use case, aliases must be used in order to distinguish the two occurrences of the table.
In the below example, for each Employee in the example database Employees table, a record is
returned containing the employee's first name together with the corresponding first name of the
employee's manager. Since managers are also employees, the table is joined with itself:
SELECT
e.FName AS "Employee",
m.FName AS "Manager"
FROM
Employees e
JOIN
Employees m
ON e.ManagerId = m.Id
Employee Manager
John James
Michael James
Johnathon John
01-01-
1 James Smith 1234567890 NULL 1 1000
2002
23-03-
2 John Johnson 2468101214 1 1 400 2005
12-05-
3 Michael Williams 1357911131 1 2 600 2009
24-07-
The first action is to create a Cartesian product of all records in the tables used in the FROM
https://riptutorial.com/ 106
clause. In this case it's the Employees table twice, so the intermediate table will look like this (I've
removed any fields not used in this example):
2 John 1 1 James
NULL
2 John 1 2 John
1
2 John 1 3 Michael
1
2 John 1 4 Johnathon
2
3 Michael 1 1 James
NULL
3 Michael 1 2 John
1
3 Michael 1 3 Michael
1
3 Michael 1 4 Johnathon 2
The next action is to only keep the records that meet the JOIN criteria, so any records where the
aliased e table ManagerId equals the aliased m table Id:
4 Johnathon 2 2 John 1
Then, each expression used within the SELECT clause is evaluated to return this table:
https://riptutorial.com/ 107
e.FName m.FName
John James
Michael James
Johnathon John
Finally, column names e.FNameand m.FNameare replaced by their alias column names, assigned
with the AS operator:
Employee Manager
John James
Michael James
Johnathon John
CROSS JOIN
Cross join does a Cartesian product of the two members, A Cartesian product means each row of
one table is combined with each row of the second table in the join. For example, if TABLEA has 20
rows and TABLEB has 20 rows, the result would be 20*20 = 400 output rows.
Using example database
Which returns:
d.Name e.FName
HR James
HR John
HR Michael
HR Johnathon
Sales James
Sales John
Sales Michael
Sales Johnathon
https://riptutorial.com/ 108
d.Name e.FName
Tech James
Tech John
Tech Michael
Tech Johnathon
It is recommended to write an explicit CROSS JOIN if you want to do a cartesian join, to highlight
that this is what you want.
Joining on a Subquery
Joining a subquery is often used when you want to get aggregate data from a child/details table
and display that along with records from the parent/header table. For example, you might want to
get a count of child records, an average of some numeric column in child records, or the top or
bottom row based on a date or numeric field. This example uses aliases, which arguable makes
queries easier to read when you have multiple tables involved. Here's what a fairly typical
subquery join looks like. In this case we are retrieving all rows from the parent table Purchase
Orders and retrieving only the first row for each parent record of the child table
PurchaseOrderLineItems.
A very interesting type of JOIN is the LATERAL JOIN (new in PostgreSQL 9.3+), which is also known
as CROSS APPLY/OUTER APPLY in SQL-Server & Oracle.
The basic idea is that a table-valued function (or inline subquery) gets applied for every row you
join.
This makes it possible to, for example, only join the first matching entry in another table.
The difference between a normal and a lateral join lies in the fact that you can use a column that
you previously joined in the subquery that you "CROSS APPLY".
Syntax:
PostgreSQL 9.3+
SQL-Server:
/*
AND
(
(__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
LIMIT 1
) AS FirstOE
https://riptutorial.com/ 110
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(@in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(@in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
) AS FirstOE
FULL JOIN
One type of JOIN that is less known, is the FULL JOIN.
(Note: FULL JOIN is not supported by MySQL as per 2016)
A FULL OUTER JOIN returns all rows from the left table, and all rows from the right table.
If there are rows in the left table that do not have matches in the right table, or if there are rows in
right table that do not have matches in the left table, then those rows will be listed, too.
Example 1 :
ON 1 = 2
Example 2:
SELECT
COALESCE(T_Budget.Year, tYear.Year) AS RPT_BudgetInYear
,COALESCE(T_Budget.Value, 0.0) AS RPT_Value
FROM T_Budget
FULL JOIN tfu_RPT_All_CreateYearInterval(@budget_year_from, @budget_year_to) AS tYear
ON tYear.Year = T_Budget.Year
Note that if you're using soft-deletes, you'll have to check the soft-delete status again in the
WHERE-clause (because FULL JOIN behaves kind-of like a UNION);
It's easy to overlook this little fact, since you put AP_SoftDeleteStatus = 1 in the join clause.
Also, if you are doing a FULL JOIN, you'll usually have to allow NULL in the WHERE-clause;
forgetting to allow NULL on a value will have the same effects as an INNER join, which is
something you don't want if you're doing a FULL JOIN.
Example:
https://riptutorial.com/ 111
SELECT
T_AccountPlan.AP_UID
,T_AccountPlan.AP_Code
,T_AccountPlan.AP_Lang_EN
,T_BudgetPositions.BUP_Budget
,T_BudgetPositions.BUP_UID
,T_BudgetPositions.BUP_Jahr
FROM T_BudgetPositions
FULL JOIN T_AccountPlan
ON T_AccountPlan.AP_UID = T_BudgetPositions.BUP_AP_UID
AND T_AccountPlan.AP_SoftDeleteStatus = 1
WHERE (1=1)
AND (T_BudgetPositions.BUP_SoftDeleteStatus = 1 OR T_BudgetPositions.BUP_SoftDeleteStatus IS
NULL)
AND (T_AccountPlan.AP_SoftDeleteStatus = 1 OR T_AccountPlan.AP_SoftDeleteStatus IS NULL)
Recursive JOINs
Recursive joins are often used to obtain parent-child data. In SQL, they are implemented with
recursive common table expressions, for example:
)
SELECT * FROM MyDescendants;
https://riptutorial.com/ 112
https://riptutorial.com/ 113
here.
As you can see, there is no dedicated NOT IN syntax for left vs. right anti semi join - we achieve
the effect simply by switching the table positions within SQL text.
Cross Join
A Cartesian product of all left with all right rows.
X Y
----- -------
Amy Lisa
https://riptutorial.com/ 114
John Lisa Lisa
Lisa Lisa Lisa
Marco Marco
Phil Marco
Amy Marco
John Marco
Lisa Marco
Marco Phil Phil
Phil Phil Phil
Amy Phil Tim
John Tim Tim
Lisa Tim Tim
Marco Vincent
Phil Vincent
Amy Vincent
John Vincent
Lisa Vincent
Marco
Phil
Amy
John
Lisa
Marco
Phil
Cross join is equivalent to an inner join with join condition which always matches, so the following
query would have returned the same result:
Self-Join
This simply denotes a table joining with itself. A self-join can be any of the join types discussed
above. For example, this is a an inner self-join:
X ---- X
Amy -----
Amy John
Amy Lisa
John Marco
Lisa Marco
Phil Marco
Amy Marco
Phil
https://riptutorial.com/ 115
Chapter 36: LIKE operator
Syntax
•Wild Card with % : SELECT * FROM [table] WHERE [column_name] Like '%Value%'
Wild Card with _ : SELECT * FROM [table] WHERE [column_name] Like 'V_n%'
Wild Card with [charlist] : SELECT * FROM [table] WHERE [column_name] Like
'V[abc]n%'
Remarks
LIKE condition in WHERE clause is used to search for column values that matches the given
pattern. Patterns are formed using following two wildcard characters
Examples
Match open-ended pattern
The % wildcard appended to the beginning or end (or both) of a string will allow 0 or more of any
character before the beginning or after the end of the pattern to match.
Using '%' in the middle will allow 0 or more characters between the two parts of the pattern to
match.
We are going to use this Employees Table:
23-03-
1 John Johnson 2468101214 1 1 400
2005
11-01-
2 Sophie Amudsen 2479100211 1 1 400 2010
06-08-
3 Ronny Smith 2462544026 2 1 600 2015
23-03-
https://riptutorial.com/ 116
Id FName LName PhoneNumber ManagerId DepartmentId Salary Hire_date
2000
Following statement matches for all records having FName containing string 'on' from Employees
Table.
06-08-
3 Ronny Smith 2462544026 2 1 600
2015
23-03-
4 Jon Sanchez 2454124602 1 1 400 2005
Following statement matches all records having PhoneNumber starting with string '246' from
Employees.
23-03-
1 John Johnson 2468101214 1 1 400
2005
06-08-
3 Ronny Smith 2462544026 2 1 600 2015
01-01-
5 Hilde Knag 2468021911 2 1 800 2000
Following statement matches all records having PhoneNumber ending with string '11' from
Employees.
11-01-
2 Sophie Amudsen 2479100211 1 1 400
2010
01-01-
5 Hilde Knag 2468021911 2 1 800 2000
https://riptutorial.com/ 117
SELECT * FROM Employees WHERE FName LIKE '__n%';
06-08-
3 Ronny Smith 2462544026 2 1 600
2015
23-03-
4 Jon Sanchez 2454124602 1 1 400 2005
_ (underscore) character can also be used more than once as a wild card to match patterns.
For example, this pattern would match "jon", "jan", "jen", etc.
These names will not be shown "jn","john","jordan", "justin", "jason", "julian", "jillian", "joann"
because in our query one underscore is used and it can skip exactly one character, so result must
be of 3 character Fname.
For example, this pattern would match "LaSt", "LoSt", "HaLt", etc.
Match any single character within the specified range (e.g.: [a-f] ) or set (e.g.: [abcdef] ).
https://riptutorial.com/ 118
SELECT * FROM Employees WHERE Fname LIKE '[lmnop]ary'
The range or set can also be negated by appending the ^ caret before the range or set:
This range pattern would not match "gary" but will match "mary":
This set pattern would not match "mary" but will match"gary":
Match any:
Must match at least one string. In this example the product type must be either 'electronics',
'books', or 'video'.
SELECT *
FROM purchase_table
WHERE product_type LIKE ANY ('electronics', 'books', 'video');
SELECT *
FROM customer_table
WHERE full_address LIKE ALL ('%united kingdom%', '%london%', '%eastern road%');
Negative selection:
Use ALL to exclude all items.
This example yields all results where the product type is not 'electronics' and not 'books' and not
'video'.
SELECT *
FROM customer_table
WHERE product_type NOT LIKE ALL ('electronics', 'books', 'video');
Following statement matches all records having FName that starts with a letter from A to F from
Employees Table.
https://riptutorial.com/ 119
If you implement a text-search as LIKE-query, you usually do it like this:
SELECT *
FROM T_Whatever
WHERE SomeField LIKE CONCAT('%', @in_SearchText, '%')
However, (apart from the fact that you shouldn't necessarely use LIKE when you can use fulltext-
search) this creates a problem when somebody inputs text like "50%" or "a_b".
So (instead of switching to fulltext-search), you can solve that problem using the LIKE-escape
statement:
SELECT *
FROM T_Whatever
WHERE SomeField LIKE CONCAT('%', @in_SearchText, '%') ESCAPE '\'
sqlCmd.Parameters.Add("@in_SearchText", newString);
// instead of sqlCmd.Parameters.Add("@in_SearchText", stringToSearch);
Note: The above algorithm is for demonstration purposes only. It will not work in cases where 1
grapheme consists out of several characters (utf-8). e.g. string stringToSearch = "Les
Mise\u0301rables"; You'll need to do this for each grapheme, not for each character. You should
not use the above algorithm if you're dealing with Asian/East-Asian/South-Asian languages. Or
rather, if you want correct code to begin with, you should just do that for each graphemeCluster.
See also ReverseString, a C# interview-question
Wildcard characters
wildcard characters are used with the SQL LIKE operator. SQL wildcards are used to search for
data within a table.
Wildcards in SQL are:%, _, [charlist], [^charlist]
https://riptutorial.com/ 120
//selects all customers with a City containing the pattern "es"
SELECT * FROM Customers
WHERE City LIKE '%es%';
Eg://selects all customers with a City starting with any character, followed by "erlin"
SELECT * FROM Customers
WHERE City LIKE '_erlin';
Eg://selects all customers with a City starting with "a", "d", or "l"
SELECT * FROM Customers
WHERE City LIKE '[adl]%';
//selects all customers with a City starting with "a", "d", or "l"
SELECT * FROM Customers
WHERE City LIKE '[a-c]%';
Eg://selects all customers with a City starting with a character that is not "a", "p", or "l"
SELECT * FROM Customers
WHERE City LIKE '[^apl]%';
or
SELECT * FROM Customers
WHERE City NOT LIKE '[apl]%' and city like '_%';
https://riptutorial.com/ 121
Chapter 37: Materialized Views
Introduction
A materialized view is a view whose results are physically stored and must be periodically
refreshed in order to remain current. They are therefore useful for storing the results of complex,
long-running queries when realtime results are not required. Materialized views can be created in
Oracle and PostgreSQL. Other database systems offer similar functionality, such as SQL Server's
indexed views or DB2's materialized query tables.
Examples
PostgreSQL example
number
--------
1
(1 row)
INSERT INTO mytable VALUES(2);
SELECT * FROM myview;
number
--------
1
(1 row)
REFRESH MATERIALIZED VIEW myview;
SELECT * FROM myview;
number
--------
1
2
(2 rows)
https://riptutorial.com/ 122
Chapter 38: MERGE
Introduction
MERGE (often also called UPSERT for "update or insert") allows to insert new rows or, if a row
already exists, to update the existing row. The point is to perform the whole set of operations
atomically (to guarantee that the data remain consistent), and to prevent communication overhead
for multiple SQL statements in a client/server system.
Examples
MERGE to make Target match Source
Note: The AND NOT EXISTS portion prevents updating records that haven't changed. Using the
INTERSECT construct allows nullable columns to be compared without special handling.
Suppose we want to know how many users have the same name. Let us create table users as
follows:
Now, we just discovered a new user named Joe and would like to take him into account. To
achieve that, we need to determine whether there is an existing row with his name, and if so,
https://riptutorial.com/ 123
update it to increment count; on the other hand, if there is no existing row, we should create it.
MySQL uses the following syntax : insert … on duplicate key update …. In this case:
Suppose we want to know how many users have the same name. Let us create table users as
follows:
Now, we just discovered a new user named Joe and would like to take him into account. To
achieve that, we need to determine whether there is an existing row with his name, and if so,
update it to increment count; on the other hand, if there is no existing row, we should create it.
PostgreSQL uses the following syntax : insert … on conflict … do update …. In this case:
https://riptutorial.com/ 124
Chapter 39: NULL
Introduction
NULL in SQL, as well as programming in general, means literally "nothing". In SQL, it is easier to
understand as "the absence of any value".
It is important to distinguish it from seemingly empty values, such as the empty string '' or the
number 0, neither of which are actually NULL.
It is also important to be careful not to enclose NULL in quotes, like 'NULL', which is allowed in
columns that accept text, but is not NULL and can cause errors and incorrect data sets.
Examples
Filtering for NULL in queries
The syntax for filtering for NULL(i.e. the absence of a value) in blocks is slightly different than
WHERE
filtering for specific values.
Note that because NULLis not equal to anything, not even to itself, using equality operators = NULL
or <> NULL (or!= NULL ) will always yield the truth value of UNKNOWN
which will be rejected by WHERE.
By default every column (except those in primary key constraint) is nullable unless we explicitly set
NOT NULL constraint.
Attempting to assign
NULLto a non-nullable column will result in an error.
INSERT INTO MyTable (MyCol1, MyCol2) VALUES (1, NULL) ; -- works fine
https://riptutorial.com/ 125
-- cannot insert
-- the value NULL into column 'MyCol1', table 'MyTable';
-- column does not allow nulls. INSERT fails.
UPDATE Employees
SET ManagerId = NULL
WHERE Id = 4
https://riptutorial.com/ 126
Chapter 40: ORDER BY
Examples
Use ORDER BY with TOP to return the top x rows based on a column's value
In this example, we can use GROUP BY not only determined the sort of the rows returned, but
also what rows are returned, since we're using TOP to limit the result set.
Let's say we want to return the top 5 highest reputation users from an unnamed popular Q&A site.
Without ORDER BY
This query returns the Top 5 rows ordered by the default, which in this case is "Id", the first column
in the table (even though it's not a column shown in the results).
returns...
DisplayName Reputation
Community 1
With ORDER BY
returns...
DisplayName Reputation
JonSkeet 865023
https://riptutorial.com/ 127
DisplayName Reputation
BalusC 65023
Hans Passant 7
0
Remarks
60163 clause at the end of a SELECT, instead of
Some versions of SQL (such as MySQL) use a TOP
LIMIT
at the beginning, for example:
6
Community 2008-09-15 1
03 2008-
Sorting by column number (instead of name)
10-03
You can use a column's number (where the leftmost column is '1') to indicate which column to
base the sort on, instead of describing the column by its name.
Pro: If you think it's likely you might change column names later, doing so won't break this code.
Con: This will generally reduce readability of the query (It's instantly clear what 'ORDER BY
Reputation' means, while 'ORDER BY 14' requires some counting, probably with a finger on the
screen.)
This query sorts result by the info in relative column position 3 from select statement instead of
column name Reputation.
https://riptutorial.com/ 128
SELECT DisplayName, JoinDate, Reputation
FROM Users
ORDER BY 3
Community 2008-09- 1
09-16
Order by Alias
2008-09-
Due to logical query processing order, alias can be used in order by.
16
SELECT DisplayName, JoinDate as jd, Reputation as rep
FROM Users
ORDER BY jd, rep
And can use relative order of the columns in the select statement .Consider the same example as
above and instead of using alias use the relative order like for display name it is 1 , for Jd it is 2
and so on
To sort this table Employee by department, you would useORDER BY Department. However, if you want
a different sort order that is not alphabetical, you have to map the Department values into different
values that sort correctly; this can be done with a CASE expression:
Name Department
Hasan IT
Yusuf HR
Hillary HR
Joe IT
Merry HR
https://riptutorial.com/ 129
Name Department
Ken Accountant
SELECT *
FROM Employee
ORDER BY CASE Department
WHEN 'HR' THEN 1
WHEN 'Accountant' THEN 2
ELSE 3
END;
Name Department
Yusuf HR HR HR
Hillary Accountant
Merry IT IT
Ken
Hasan
Joe
https://riptutorial.com/ 130
Chapter 41: Order of Execution
Examples
Logical Order of Query Processing in SQL
VT stands for 'Virtual Table' and shows how various data is produced as the query is processed
1. FROM: A Cartesian product (cross join) is performed between the first two tables in the
FROM clause, and as a result, virtual table VT1 is generated.
2. ON: The ON filter is applied to VT1. Only rows for which the is TRUE are inserted to VT2.
3. OUTER (join): If an OUTER JOIN is specified (as opposed to a CROSS JOIN or an INNER
JOIN), rows from the preserved table or tables for which a match was not found are added to
the rows from VT2 as outer rows, generating VT3. If more than two tables appear in the
FROM clause, steps 1 through 3 are applied repeatedly between the result of the last join
and the next table in the FROM clause until all tables are processed.
4. WHERE: The WHERE filter is applied to VT3. Only rows for which the is TRUE are inserted
to VT4.
5. GROUP BY: The rows from VT4 are arranged in groups based on the column list specified in
the GROUP BY clause. VT5 is generated.
6. CUBE | ROLLUP: Supergroups (groups of groups) are added to the rows from VT5,
generating VT6.
7. HAVING: The HAVING filter is applied to VT6. Only groups for which the is TRUE are
inserted to VT7.
10. ORDER BY: The rows from VT9 are sorted according to the column list specified in the
https://riptutorial.com/ 131
ORDER BY clause. A cursor is generated (VC10).
11. TOP: The specified number or percentage of rows is selected from the beginning of VC10.
Table VT11 is generated and returned to the caller. LIMIT has the same functionality as TOP
in some SQL dialects such as Postgres and Netezza.
https://riptutorial.com/ 132
Chapter 42: Primary Keys
Syntax
•MySQL: CREATE TABLE Employees ( Id int NOT NULL, PRIMARY KEY (Id), ... );
•Others: CREATE TABLE Employees ( Id int NOT NULL PRIMARY KEY, ... );
Examples
Creating a Primary Key
This will create the Employees table with 'Id' as its primary key. The primary key can be used to
uniquely identify the rows of a table. Only one primary key is allowed per table.
A key can also be composed by one or more fields, so called composite key, with the following
syntax:
Many databases allow to make the primary key value automatically increment when a new key is
added. This ensures that every key is different.
MySQL
PostgreSQL
https://riptutorial.com/ 133
SQL Server
SQLite
https://riptutorial.com/ 134
Chapter 43: Relational Algebra
Examples
Overview
Relational Algebra is not a full-blown SQL language, but rather a way to gain theoretical
understanding of relational processing. As such it shouldn't make references to physical entities
such as tables, records and fields; it should make references to abstract constructs such as
relations, tuples and attributes. Saying that, I won't use the academic terms in this document and
will stick to the more widely known layman terms - tables, records and fields.
A couple of rules of relational algebra before we get started:
•The operators used in relational algebra work on whole tables rather than individual records.
•The result of a relational expression will always be a table (this is called the closure property)
SELECT
The select operator returns a subset of the main table.
select < table > where < condition >
For example, examine the expression:
This will result in table whose records comprises of all records in the People table where the
DepartmentID value is equal to 2:
https://riptutorial.com/ 135
Conditions can also be joined to restrict the expression further:
PROJECT
The project operator will return distinct field values from a table.
project < table > over < field list >
For example, examine the following expression:
project People over StartYear
This can be written as:
This will result in a table comprising of the distinct values held within the StartYear field of the
People table.
Duplicate values are removed from the resulting table due to the closure property creating a
relational table: all records in a relational table are required to be distinct.
If the field list comprises more than a single field then the resulting table is a distinct version of
these fields.
project People over StartYear, DepartmentID will return:
One record is removed due to the duplication of 2006 StartYear and 1 DepartmentID.
https://riptutorial.com/ 136
GIVING
Relational expressions can be chained together by naming the individual expressions using the
giving keyword, or by embedding one expression within another.
< relational algebra expression > giving < alias name >
This will result in table B below, with table A being the result of the first expression.
The first expression is evaluated and the resulting table is given the alias A. This table is then
used within the second expression to give the final table with an alias of B.
Another way of writing this expression is to replace the table alias name in the second expression
with the entire text of the first expression enclosed within brackets:
project (select People where DepartmentID = 2) over PersonName giving B
NATURAL JOIN
A natural join sticks two tables together using a common field shared between the tables.
join < table 1 > and < table 2 > where < field 1 > = < field 2 >
assuming that < field 1 > is in < table 1 > and < field 2 > is in < table 2 >.
For example, the following join expression will join People and Departments based on the
DepartmentID and ID columns in the respective tables:
join People and Departments where DepartmentID = ID
https://riptutorial.com/ 137
Note that only DepartmentID from the People table is shown and not ID from the Department
table. Only one of the fields being compared needs to be shown which is generally the field name
from the first table in the join operation.
Although not shown in this example it is possible that joining tables may result in two fields having
the same heading. For example, if I had used the heading Name to identify the PersonName and
Dept fields (i.e. to identify the Person Name and the Department Name). When this situation
arises we use the table name to qualify the field names using the dot notation: People.Name and
Departments.Name
join combined with select and project can be used together to pull information:
or as a combined expression:
project (select (join People and Departments where DepartmentID = ID) where StartYear =
2005 and Dept = 'Production') over PersonName giving C
This will result in this table:
ALIAS
DIVIDE
UNION
INTERSECTION
DIFFERENCE
UPDATE ( := )
TIMES
https://riptutorial.com/ 138
Read Relational Algebra online: https://riptutorial.com/sql/topic/7311/relational-algebra
https://riptutorial.com/ 139
Chapter 44: Row number
Syntax
•ROW_NUMBER ( )
•OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause )
Examples
Row numbers without partitions
Include a row number according to the order specified.
SELECT
ROW_NUMBER() OVER(ORDER BY Fname ASC) AS RowNumber,
Fname,
LName
FROM Employees
SELECT
ROW_NUMBER() OVER(PARTITION BY DepartmentId ORDER BY DepartmentId ASC) AS RowNumber,
DepartmentId, Fname, LName
FROM Employees
WITH cte AS (
SELECT ProjectID,
ROW_NUMBER() OVER (PARTITION BY ProjectID ORDER BY InsertDate DESC) AS rn
FROM ProjectNotes
)
DELETE FROM cte WHERE rn > 1;
https://riptutorial.com/ 140
Chapter 45: SELECT
Introduction
The SELECT statement is at the heart of most SQL queries. It defines what result set should be
returned by the query, and is almost always used in conjunction with the FROM clause, which
defines what part(s) of the database should be queried.
Syntax
Remarks
SELECT determines which columns' data to return and in which order FROM a given table
(given that they match the other requirements in your query specifically - where and having filters
and joins).
will only return results from theNameand Serial Number columns, but not from the column called
Rank, for example
SELECT *
FROM ArmyInfo
indicates that all columns will be returned. However, please note that it is poor practice to SELECT *
as you are literally returning all columns of a table.
Examples
Using the wildcard character to select all columns in a query.
Consider a database with the following two tables.
Employees table:
https://riptutorial.com/ 141
Id FName LName DeptI
2 John Johnson
Departments table:
Id Name
1 Sales
2 Marketing
3 Finance
4 IT
When used as a substitute for explicit column names, it returns all columns in all tables that a
query is selecting FROM. This effect applies to all tables the query accesses through its JOIN
clauses.
1 James Smith 3
2 John Johnson 4
Dot notation
To select all values from a specific table, the wildcard character can be applied to the table with
dot notation.
Consider the following query:
SELECT
Employees.*,
Departments.Name
https://riptutorial.com/ 142
FROM
Employees
JOIN
Departments
ON Departments.Id = Employees.DeptId
This will return a data set with all fields on the Employee table, followed by just the Name field in the
Departments table:
2 John Johnson 4 IT
It is generally advised that using * is avoided in production code where possible, as it can cause a
number of potential problems including:
1. Excess IO, network load, memory use, and so on, due to the database engine reading data
that is not needed and transmitting it to the front-end code. This is particularly a concern
where there might be large fields such as those used to store long notes or attached files.
2. Further excess IO load if the database needs to spool internal results to disk as part of the
processing for a query more complex than SELECT <columns> FROM <table>.
3. Extra processing (and/or even more IO) if some of the unneeded columns are:
•computed columns in databases that support them
•in the case of selecting from a view, columns from a table/view that the query optimiser
could otherwise optimise out
4. The potential for unexpected errors if columns are added to tables and views later that
results ambiguous column names. For example SELECT * FROM orders JOIN people ON
people.id = orders.personid ORDER BY displayname - if a column column called displayn
added to the orders table to allow users to give their orders meaningful names for future
reference then the column name will appear twice in the output so the ORDER BY clause will be
ambiguous which may cause errors ("ambiguous column name" in recent MS SQL Server
versions), and if not in this example your application code might start displaying the order
name where the person name is intended because the new column is the first of that name
returned, and so on.
While best avoided in production code, using * is fine as a shorthand when performing manual
queries against the database for investigation or prototype work.
Sometimes design decisions in your application make it unavoidable (in such circumstances,
prefer tablealias.* over just * where possible).
When using EXISTS, such as SELECT A.col1, A.Col2 FROM A WHERE EXISTS (SELECT * FROM B
A.ID = B.A_ID)
https://riptutorial.com/ 143
, we are not returning any data from B. Thus a join is unnecessary, and the engine knows no
values from B are to be returned, thus no performance hit for using *. Similarly COUNT(*) is fine as it
also doesn't actually return any of the columns, so only needs to read and process those that are
used for filtering purposes.
Selecting with Condition
The [condition] can be any SQL expression, specified using comparison or logical operators like >,
<, =, <>, >=, <=, LIKE, NOT, IN, BETWEEN etc.
The following statement returns all columns from the table 'Cars' where the status column is
'READY':
SELECT
PhoneNumber,
Email,
PreferredContact
FROM Customers
This statement will return the columns PhoneNumber, Email, and PreferredContact from all rows of the
Customers table. Also the columns will be returned in the sequence in which they appear in the
SELECT clause.
The result will be:
If multiple tables are joined together, you can select columns from specific tables by specifying the
table name before the column name: [table_name].[column_name]
https://riptutorial.com/ 144
SELECT
Customers.PhoneNumber,
Customers.Email,
Customers.PreferredContact,
Orders.Id AS OrderId
FROM
Customers
LEFT JOIN
Orders ON Orders.CustomerId = Customers.Id
*AS OrderId means that the Id field of Orders table will be returned as a column named OrderId. See
selecting with column alias for further information.
To avoid using long table names, you can use table aliases. This mitigates the pain of writing long
table names for each field that you select in the joins. If you are performing a self join (a join
between two instances of the same table), then you must use table aliases to distinguish your
tables. We can write a table alias like Customers c or Customers AS c. Here c works as an alias for
Customers and we can select let's say Email like this: c.Email.
SELECT
c.PhoneNumber,
c.Email,
c.PreferredContact,
o.Id AS OrderId
FROM
Customers c
LEFT JOIN
Orders o ON o.CustomerId = c.Id
Column aliases are used mainly to shorten code and make column names more readable.
Code becomes shorter as long table names and unnecessary identification of columns (e.g., there
may be 2 IDs in the table, but only one is used in the statement) can be avoided. Along with table
aliases this allows you to use longer descriptive names in your database structure while keeping
queries upon that structure concise.
Furthermore they are sometimes required, for instance in views, in order to name computed
outputs.
All versions of SQL
Aliases can be created in all versions of SQL using double quotes (").
SELECT
FName AS "First Name",
MName AS "Middle Name",
LName AS "Last Name"
FROM Employees
https://riptutorial.com/ 145
Different Versions of SQL
You can use single quotes ('), double quotes (") and square brackets (
Microsoft SQL Server. [] ) to create an alias in
SELECT
FName AS "First Name",
MName AS 'Middle Name',
LName AS [Last Name]
FROM Employees
This statement will return FName and LName columns with a given name (an alias). This is achieved
using the AS operator followed by the alias, or simply writing alias directly after the column name.
This means that the following query has the same outcome as the above.
SELECT
FName "First Name",
MName "Middle Name",
LName "Last Name"
FROM Employees
However, the explicit version (i.e., using the AS operator) is more readable.
If the alias has a single word that is not a reserved word, we can write it without single quotes,
double quotes or brackets:
SELECT
FName AS FirstName,
LName AS LastName
FROM Employees
https://riptutorial.com/ 146
FirstName LastName
James Smith
John Johnson
Michael Williams
Some find using = instead of As easier to read, though many recommend against this format,
mainly because it is not standard so not widely supported by all databases. It may cause
confusion with other uses of the = character.
Also, if you need to use reserved words, you can use brackets or quotes to escape:
SELECT
FName as "SELECT",
MName as "FROM",
LName as "WHERE"
FROM Employees
https://riptutorial.com/ 147
Likewise, you can escape keywords in MSSQL with all different approaches:
SELECT
FName AS "SELECT",
MName AS 'FROM',
LName AS [WHERE]
FROM Employees
SELECT FROM
WHERE
James John
Smith
John James
Johnson
Also, a column alias may be used any of the final clauses of the same query, such as an ORDER BY:
SELECT
FName AS FirstName,
LName AS LastName
FROM
Employees
ORDER BY
LastName DESC
SELECT
FName AS SELECT,
LName AS FROM
FROM
Employees
ORDER BY
LastName DESC
This statement will return all the columns from the tableEmployees.
https://riptutorial.com/ 148
Id FName LName PhoneNumber
Or
This example will sort the results first by LNameand then, for records that have the same LName, sort
by FName. This will give you a result similar to what you would find in a telephone book.
In order to save retyping the column name in the ORDER BY clause, it is possible to use instead the
column's number. Note that column numbers start from 1.
SELECT Id, FName, LName, PhoneNumber FROM Employees ORDER BY CASE WHEN LName='Jones` THEN 0
ELSE 1 END ASC
This will sort your results to have all records with the LName of "Jones" at the top.
When a column name matches a reserved keyword, standard SQL requires that you enclose it in
double quotation marks:
SELECT
"ORDER",
ID
FROM ORDERS
Some DBMSes have proprietary ways of quoting names. For example, SQL Server uses square
brackets for this purpose:
SELECT
[Order],
ID
https://riptutorial.com/ 149
FROM ORDERS
SELECT
`Order`,
id
FROM orders
The SQL 2008 standard defines the FETCH FIRST clause to limit the number of records returned.
This standard is only supported in recent versions of some RDMSs. Vendor-specific non-standard
syntax is provided in other systems. Progress OpenEdge 11.x also supports the FETCH FIRST <n>
ROWS ONLY syntax.
Additionally, OFFSET <m> ROWS before FETCH FIRST <n> ROWS ONLY allows skipping rows before fetch
rows.
https://riptutorial.com/ 150
Results: 10 records.
Vendor Nuances:
It is important to note that the TOP in Microsoft SQL operates after the WHERE clause and will return
the specified number of results if they exist anywhere in the table, while ROWNUM works as part of the
WHERE clause so if other conditions do not exist in the specified number of rows at the beginning of
the table, you will get zero results when there could be others to be found.
Selecting with table alias
The Employees table is given the alias 'e' directly after the table name. This helps remove
ambiguity in scenarios where multiple tables have the same field name and you need to be
specific as to which table you want to return data from.
Note that once you define an alias, you can't use the canonical table name anymore. i.e.,
It is worth noting table aliases -- more formally 'range variables' -- were introduced into the SQL
language to solve the problem of duplicate columns caused by INNER JOIN. The 1992 SQL
standard corrected this earlier design flaw by introducing NATURAL JOIN (implemented in mySQL,
PostgreSQL and Oracle but not yet in SQL Server), the result of which never has duplicate column
names. The above example is interesting in that the tables are joined on columns with different
names (Id and ManagerId) but are not supposed to be joined on the columns with the same name (
LName, FName), requiring the renaming of the columns to be performed before the join:
https://riptutorial.com/ 151
SELECT Fname, LName, ManagerFirstName
FROM Employees
NATURAL JOIN
( SELECT Id AS ManagerId, Fname AS ManagerFirstName
FROM Managers ) m;
Note that although an alias/range variable must be declared for the dervied table (otherwise SQL
will throw an error), it never makes sense to actually use it in the query.
Select rows from multiple tables
SELECT *
FROM
table1,
table2
SELECT
table1.column1,
table1.column2,
table2.column1
FROM
table1,
table2
These statements return the selected columns from multiple tables in one query.
There is no specific relationship between the columns returned from each table.
Average
The AVG() aggregate function will return the average of values selected.
If employee is categorized with multiple department and we want to find avg salary for every
department then we can use following query.
https://riptutorial.com/ 152
Minimum
The MIN() aggregate function will return the minimum of values selected.
Maximum
The MAX() aggregate function will return the maximum of values selected.
Count
The COUNT() aggregate function will return the count of values selected.
It can also be combined with where conditions to get the count of rows that satisfy specific
conditions.
Specific columns can also be specified to get the number of values in the column. Note that NULL
Count can also be combined with the distinct keyword for a distinct count.
Sum
The SUM() aggregate function returns the sum of the values selected for all rows.
https://riptutorial.com/ 153
Selection with nulls take a different syntax. Don't use =, use IS NULL or IS NOT NULL instead.
Selecting with CASE
When results need to have some logic applied 'on the fly' one can use CASE statement to
implement it.
SELECT CASE WHEN Col1 < 50 THEN 'under' ELSE 'over' END threshold
FROM TableName
SELECT
CASE WHEN Col1 < 50 THEN 'under'
WHEN Col1 > 50 AND Col1 <100 THEN 'between'
ELSE 'over'
END threshold
FROM TableName
SELECT
CASE WHEN Col1 < 50 THEN 'under'
ELSE
CASE WHEN Col1 > 50 AND Col1 <100 THEN Col1
ELSE 'over' END
END threshold
FROM TableName
Sometimes when tables are used mostly (or only) for reads, indexing does not help anymore and
every little bit counts, one might use selects without LOCK to improve performance.
SQL Server
MySQL
Oracle
https://riptutorial.com/ 154
DB2
If used on table that has record modifications going on might have unpredictable results.
This query will return all DISTINCT (unique, different) values from ContinentCode column from
Countries table
ContinentCode
OC
EU
AS
NA
AF
SQLFiddle Demo
https://riptutorial.com/ 155
Getting average income by department:
The important thing is to select only columns specified in the GROUP BY clause or used with
aggregate functions.
There WHERE clause can also be used with GROUP BY, but WHERE filters out records before any
grouping is done:
If you need to filter the results after the grouping has been done, e.g, to see only departments
whose average income is larger than 1000, you need to use the HAVING clause:
Sam 18 M
John 21 M
Bob 22 M
Mary 23 F
SELECT name FROM persons WHERE gender = 'M' AND age > 20;
Name
John
Bob
https://riptutorial.com/ 156
using OR keyword
SELECT name FROM persons WHERE gender = 'M' OR age < 20;
name
Sam
John
Bob
These keywords can be combined to allow for more complex criteria combinations:
SELECT name
FROM persons
WHERE (gender = 'M' AND age < 20)
OR (gender = 'F' AND age > 20);
name
Sam
Mary
https://riptutorial.com/ 157
Chapter 46: Sequence
Examples
Create Sequence
Using Sequences
a reference to seq_name.NEXTVAL is used to get the next value in a sequence. A single
statement can only generate a single sequence value. If there are multiple references to
NEXTVAL in a statement, they use will use the same generated number.
NEXTVAL can be used for INSERTS
UPDATE Orders
SET Order_UID = orders_seq.NEXTVAL
WHERE Customer = 581;
https://riptutorial.com/ 158
Chapter 47: SKIP TAKE (Pagination)
Examples
Skipping some rows from result
ISO/ANSI SQL:
MySQL:
Oracle:
SELECT Id,
Col1
FROM (SELECT Id, Col1, row_number() over (order by Id)
RowNumber
FROM TableName)
WHERE RowNumber > 20
PostgreSQL:
SQLite:
Oracle:
https://riptutorial.com/ 159
SELECT Id,
Col1
FROM (SELECT Id, Col1, row_number() over (order by Id)
RowNumber
FROM TableName)
WHERE RowNumber <= 20
SQL Server:
SELECT TOP 20 *
FROM dbo.[Sale]
ISO/ANSI SQL:
MySQL:
SELECT Id,
Col1
FROM (SELECT Id,
Col1,
row_number() over (order by Id) RowNumber
FROM TableName)
WHERE RowNumber BETWEEN 21 AND 40
PostgreSQL; SQLite:
https://riptutorial.com/ 160
Chapter 48: SQL CURSOR
Examples
Example of a cursor that queries all rows by index for each database
Here, a cursor is used to loop through all databases.
Futhermore, a cursor from dynamic sql is used to query each database returned by the first cursor.
This is to demonstrate the connection-scope of a cursor.
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @db_name
WHILE @@FETCH_STATUS = 0
BEGIN
OPEN columns_cursor
FETCH NEXT FROM columns_cursor
INTO @schema, @table, @column
https://riptutorial.com/ 161
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @schema + '.' + @table + '.' + @column
--EXEC asp_DoSomethingStoredProc @UserId
https://riptutorial.com/ 162
Chapter 49: SQL Group By vs Distinct
Examples
Difference between GROUP BY and DISTINCT
GROUP BY is used in combination with aggregation functions. Consider the following table:
1 43 Store A 25 20-03-2016
2 57 Store B 50 22-03-2016
3 43 Store A 30 25-03-2016
4 82 Store C 10 26-03-2016
5 21 Store A 45 29-03-2016
SELECT
storeName,
COUNT(*) AS total_nr_orders,
COUNT(DISTINCT userId) AS nr_unique_customers,
AVG(orderValue) AS average_order_value,
MIN(orderDate) AS first_order,
MAX(orderDate) AS lastOrder
FROM
orders
GROUP BY
storeName;
29-03- 20-03-
Store A 3 2 33.3
2016 2016
22-03- 22-03-
Store B 1 1 50 2016
2016
26-03- 26-03-
Store
2016 C 1 1 10 2016
While DISTINCT is used to list a unique combination of distinct values for the specified columns.
https://riptutorial.com/ 163
SELECT DISTINCT
storeName,
userId
FROM
orders;
storeName userId
Store A 4
Store B 3
Store C 5
Store A 7
8
Read SQL Group By vs Distinct online: https://riptutorial.com/sql/topic/2499/sql-group-by-vs-
distinct 2
https://riptutorial.com/ 164
Chapter 50: SQL Injection
Introduction
SQL injection is an attempt to access a website's database tables by injecting SQL into a form
field. If a web server does not protect against SQL injection attacks, a hacker can trick the
database into running the additional SQL code. By executing their own SQL code, hackers can
upgrade their account access, view someone else's private information, or make any other
modifications to the database.
Examples
SQL injection sample
Assuming the call to your web application's login handler looks like this:
https://somepage.com/ajax/login.ashx?username=admin&password=123
strUserName = getHttpsRequestParameterString("username");
strPassword = getHttpsRequestParameterString("password");
and query your database to determine whether a user with that password exists.
txtSQL = "SELECT * FROM Users WHERE username = '" + strUserName + "' AND password = '"+
strPassword +"'";
This will work if the username and password do not contain a quote.
However, if one of the parameters does contain a quote, the SQL that gets sent to the database
will look like this:
-- strUserName = "d'Alambert";
txtSQL = "SELECT * FROM Users WHERE username = 'd'Alambert' AND password = '123'";
This will result in a syntax error, because the quote after the in
d d'Alambert ends the SQL string.
You could correct this by escaping quotes in username and password, e.g.:
https://riptutorial.com/ 165
cmd.CommandText = "SELECT * FROM Users WHERE username = @username AND password = @password";
cmd.Parameters.Add("@username", strUserName);
cmd.Parameters.Add("@password", strPassword);
If you do not use parameters, and forget to replace quote in even one of the values, then a
malicious user (aka hacker) can use this to execute SQL commands on your database.
For example, if an attacker is evil, he/she will set the password to
"SELECT * FROM Users WHERE username = 'somebody' AND password = 'lol'; DROP DATABASE master; -
-'";
Unfortunately for you, this is valid SQL, and the DB will execute this!
There are many other things a malicious user could do, such as stealing every user's email
address, steal everyone's password, steal credit card numbers, steal any amount of data in your
database, etc.
SQL = "SELECT * FROM Users WHERE username = '" + user + "' AND password ='" + pw + "'";
db.execute(SQL);
Then a hacker could retrieve your data by giving a password like pw' or '1'='1 ; the resulting SQL
statement will be:
SELECT * FROM Users WHERE username = 'somebody' AND password ='pw' or '1'='1'
This one will pass the password check for all rows in the Users table because '1'='1' is always
true.
To prevent this, use SQL parameters:
https://riptutorial.com/ 166
Read SQL Injection online: https://riptutorial.com/sql/topic/3517/sql-injection
https://riptutorial.com/ 167
Chapter 51: Stored Procedures
Remarks
Stored Procedures are SQL statements stored in the database that can be executed or called in
queries. Using a stored procedure allows encapsulation of complicated or frequently used logic,
and improves query performance by utilizing cached query plans. They can return any value a
standard query can return.
Other benefits over dynamic SQL expressions are listed on Wikipeida.
Examples
Create and call a stored procedure
Stored procedures can be created through a database management GUI (SQL Server example),
or through a SQL statement as follows:
https://riptutorial.com/ 168
Chapter 52: String Functions
Introduction
String functions perform operations on string values and return either numeric or string values.
Using string functions, you can, for example, combine data, extract a substring, compare strings,
or convert a string to all uppercase or lowercase characters.
Syntax
Remarks
String functions reference for Transact-SQL / Microsoft
Examples
Trim empty spaces
Trim is used to remove write-space at the beginning or end of selection
https://riptutorial.com/ 169
SELECT TRIM(' Hello ') --returns 'Hello'
Concatenate
In (standard ANSI/ISO) SQL, the operator for string concatenation is
by all major databases except SQL Server: || . This syntax is supported
Some databases support using CONCATto join more than two strings (Oracle does not):
Some databases (e.g., Oracle) perform implicit lossless conversions. For example, a CONCATon a
CLOBand NCLOB
yields a NCLOB . A CONCATon a number and a varchar2 results in a varchar2 , etc.:
Some databases can use the non-standard + operator (but in most, works
+ only for numbers):
On SQL Server < 2012, where CONCAT is not supported, +is the only way to join strings.
Substring
Syntax is: SUBSTRING ( string_expression, start, length ) . Note that SQL strings are 1-indexed.
This is often used in conjunction with the LEN() function to get the last n characters of a string of
unknown length.
https://riptutorial.com/ 170
DECLARE @str1 VARCHAR(10) = 'Hello', @str2 VARCHAR(10) = 'FooBarBaz';
SELECT SUBSTRING(@str1, LEN(@str1) - 2, 3) --returns 'llo'
SELECT SUBSTRING(@str2, LEN(@str2) - 2, 3) --returns 'Baz'
Split
Splits a string expression using a character separator. Note that
STRING_SPLIT() is a table-valued
function.
SELECT value FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ');
Result:
value
-----
Lorem
ipsum
dolor
sit
amet.
Stuff
Stuff a string into another, replacing 0 or more characters at a certain position.
Syntax:
Example:
Length
SQL Server
https://riptutorial.com/ 171
SELECT DATALENGTH('Hello '); -- returns 6
It should be noted though, that DATALENGTH returns the length of the underlying byte
representation of the string, which depends, i.a., on the charset used to store the string.
DECLARE @str varchar(100) = 'Hello ' --varchar is usually an ASCII string, occupying 1 byte
per char
SELECT DATALENGTH(@str) -- returns 6
DECLARE @nstr nvarchar(100) = 'Hello ' --nvarchar is a unicode string, occupying 2 bytes per
char
SELECT DATALENGTH(@nstr) -- returns 12
Oracle
Examples:
REPLACE( String to search , String to search for and replace , String to place into the original string
)
Example:
SELECT REPLACE( 'Peter Steve Tom', 'Steve', 'Billy' ) --Return Values: Peter Billy Tom
LEFT - RIGHT
Syntax is:
LEFT ( string-expression , integer )
RIGHT ( string-expression , integer )
Oracle SQL doesn't have LEFT and RIGHT functions. They can be emulated with SUBSTR and
LENGTH.
SUBSTR ( string-expression, 1, integer )
https://riptutorial.com/ 172
SUBSTR ( string-expression, length(string-expression)-integer+1, integer)
REVERSE
REPLICATE
The REPLICATE function concatenates a string with itself a specified number of times.
REGEXP
MySQL3.19
The Replace function in SQL is used to update the content of a string. The function call is
REPLACE( ) for MySQL, Oracle, and SQL Server.
The syntax of the Replace function is:
The following example replaces occurrences of South with Southern in Employees table:
FirstName Address
https://riptutorial.com/ 173
Select Statement :
SELECT
FirstName,
REPLACE (Address, 'South', 'Southern') Address
FROM Employees
ORDER BY FirstName
Result:
FirstName Address
Update Statement :
We can use a replace function to make permanent changes in our table through following
approach.
Update Employees
Set city = (Address, 'South', 'Southern');
A more common approach is to use this in conjunction with a WHERE clause like this:
Update Employees
Set Address = (Address, 'South', 'Southern')
Where Address LIKE 'South%';
PARSENAME
DATABASE : SQL Server
PARSENAME function returns the specific part of given string(object name). object name may
contains string like object name,owner name, database name and server name.
More details MSDN:PARSENAME
Syntax
PARSENAME('NameOfStringToParse',PartIndex)
Example
https://riptutorial.com/ 174
SELECT PARSENAME('ServerName.DatabaseName.SchemaName.ObjectName',1) // returns `ObjectName`
SELECT PARSENAME('[1012-1111].SchoolDatabase.school.Student',1) // returns `Student`
PARSENAME will returns null is specified part is not present in given object name string
INSTR
Return the index of the first occurrence of a substring (zero if not found)
https://riptutorial.com/ 175
Chapter 53: Subqueries
Remarks
Subqueries can appear in different clauses of an outer query, or in the set operation. They must be
Examples
Subquery in WHERE clause
Use a subquery to filter the result set. For example this will return all employees with a salary equal
to the highest paid employee.
SELECT *
FROM Employees
WHERE Salary = (SELECT MAX(Salary) FROM Employees)
A subquery in a FROM clause acts similarly to a temporary table that is generated during the
execution of a query and lost afterwards.
SELECT
Id, FName, LName, (SELECT COUNT(*) FROM Cars WHERE Cars.CustomerId = Customers.Id) AS
NumberOfCars
FROM Customers
You can use subqueries to define a temporary table and use it in the FROM clause of an "outer"
query.
https://riptutorial.com/ 176
SELECT * FROM (SELECT city, temp_hi - temp_lo AS temp_var FROM weather) AS w
WHERE temp_var > 20;
The above finds cities from the weather table whose daily temperature variation is greater than 20.
The result is:
city temp_var
ST LOUIS 21
LOS ANGELES 31
LOS ANGELES 23
LOS ANGELES 31
LOS ANGELES 27
LOS ANGELES 28
LOS ANGELES 28
LOS ANGELES 32
The following example finds cities (from the cities example) whose population is below the
average temperature (obtained via a sub-qquery):
Here: the subquery (SELECT avg(pop2000) FROM cities) is used to specify conditions in the
WHERE clause. The result is:
name pop2000
ST LOUIS 348189
Subqueries can also be used in the SELECT part of the outer query. The following query shows all
https://riptutorial.com/ 177
weather table columns with the corresponding states from the cities table.
SELECT w.*, (SELECT c.state FROM cities AS c WHERE c.name = w.city ) AS state
FROM weather AS w;
SELECT *
FROM Employees
WHERE EmployeeID not in (SELECT EmployeeID
FROM Supervisors)
SELECT *
FROM Employees AS e
LEFT JOIN Supervisors AS s ON s.EmployeeID=e.EmployeeID
WHERE s.EmployeeID is NULL
Correlated Subqueries
Correlated (also known as Synchronized or Coordinated) Subqueries are nested queries that
make references to the current row of their outer query:
SELECT EmployeeId
FROM Employee AS eOuter
WHERE Salary > (
SELECT AVG(Salary)
FROM Employee eInner
WHERE eInner.DepartmentId = eOuter.DepartmentId
)
Subquery SELECT AVG(Salary) ... is correlated because it refers to Employee row eOuter from its
outer query.
Read Subqueries online: https://riptutorial.com/sql/topic/1606/subqueries
https://riptutorial.com/ 178
Chapter 54: Synonyms
Examples
Create Synonym
CREATE SYNONYM
EmployeeData FOR
MyDatabase.dbo.Employees
https://riptutorial.com/ 179
Chapter 55: Table Design
Remarks
The Open University (1999) Relational Database Systems: Block 2 Relational Theory, Milton
Keynes, The Open University.
Examples
Properties of a well designed table.
A true relational database must go beyond throwing data into a few tables and writing some SQL
statements to pull that data out. At best a badly designed table structure will slow the execution of
queries and could make it impossible for the database to function as intended.
A database table should not be considered as just another table; it has to follow a set of rules to
be considered truly relational. Academically it is referred to as a 'relation' to make the distinction.
The five rules of a relational table are:
1. Each value is atomic; the value in each field in each row must be a single value.
2. Each field contains values that are of the same data type.
3. Each field heading has a unique name.
4. Each row in the table must have at least one value that makes it unique amongst the other
records in the table.
5. The order of the rows and columns has no significance.
1 Fred 11/02/1971 3
2 Fred 11/02/1971 3
3 Sue 08/07/1975 2
•Rule 1: Each value is atomic. Id, Name, DOB and Manager only contain a single value.
•Rule 2: Id contains only integers, Name contains text (we could add that it's text of four
characters or less), DOB contains dates of a valid type and Manager contains integers (we could
add that corresponds to a Primary Key field in a managers table).
•Rule 3: Id, Name, DOB and Manager are unique heading names within the table.
•Rule 4: The inclusion of the Id field ensures that each record is distinct from any other record
within the table.
https://riptutorial.com/ 180
A badly designed table:
1 Fred 11/02/1971 3
1 Fred 11/02/1971 3
https://riptutorial.com/ 181
Chapter 56: Transactions
Remarks
A transaction is a logical unit of work containing one or more steps, each of which must complete
successfully in order for the transaction to commit to the database. If there are errors, then all of
the data modifications are erased and the database is rolled back to its initial state at the start of
the transaction.
Examples
Simple Transaction
BEGIN TRANSACTION
INSERT INTO DeletedEmployees(EmployeeID, DateDeleted, User)
(SELECT 123, GetDate(), CURRENT_USER);
DELETE FROM Employees WHERE EmployeeID = 123;
COMMIT TRANSACTION
Rollback Transaction
When something fails in your transaction code and you want to undo it, you can rollback your
transaction:
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO Users(ID, Name, Age)
VALUES(1, 'Bob', 24)
DELETE FROM Users WHERE Name = 'Todd'
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
https://riptutorial.com/ 182
Chapter 57: Triggers
Examples
CREATE TRIGGER
This example creates a trigger that inserts a record to a second table (MyAudit) after a record is
inserted into the table the trigger is defined on (MyTable). Here the "inserted" table is a special
table used by Microsoft SQL Server to store affected rows during INSERT and UPDATE
statements; there is also a special "deleted" table that performs the same function for DELETE
statements.
AS
BEGIN
https://riptutorial.com/ 183
Chapter 58: TRUNCATE
Introduction
The TRUNCATE statement deletes all data from a table. This is similar to DELETE with no filter,
but, depending on the database software, has certain restrictions and optimizations.
Syntax
Remarks
TRUNCATE is a DDL (Data Definition Language) command, and as such there are significant
differences between it and DELETE (a Data Manipulation Language, DML, command). While
TRUNCATE can be a means of quickly removing large volumes of records from a database, these
differences should be understood in order to decide if using a TRUNCATE command is suitable in
your particular situation.
•TRUNCATE is a data page operation. Therefore DML triggers (ON DELETE) associated with
the table won't fire when you perform a TRUNCATE operation. While this will save a large
amount of time for massive delete operations, however you may then need to manually
delete the related data.
•TRUNCATE will release the disk space used by the deleted rows, DELETE will release
space
•If the table to be truncated uses identity columns (MS SQL Server), then the seed is reset by
the TRUNCATE command. This may result referential integrity problems
•Depending the security roles in place and the variant of SQL in use, you may not have the
necessary permissions to perform a TRUNCATE command
Examples
Removing all rows from the Employee table
Using truncate table is often better then using DELETE TABLE as it ignores all the indexes and
triggers and just removes everything.
Delete table is a row based operation this means that each row is deleted. Truncate table is a data
page operation the entire data page is reallocated. If you have a table with a million rows it will be
much faster to truncate the table than it would be to use a delete table statement.
Though we can delete specific Rows with DELETE, we cannot TRUNCATE specific rows, we can
https://riptutorial.com/ 184
only TRUNCATE all the records at once. Deleting All rows and then inserting a new record will
continue to add the Auto incremented Primary key value from the previously inserted value, where
as in Truncate, the Auto Incremental primary key value will also get reset and starts from 1.
Note that when truncating table, no foreign keys must be present, otherwise you will get an
error.
Read TRUNCATE online: https://riptutorial.com/sql/topic/1466/truncate
https://riptutorial.com/ 185
Chapter 59: TRY/CATCH
Remarks
TRY/CATCH is a language construct specific to MS SQL Server's T-SQL.
It allows error handling within T-SQL, similar to that seen in .NET code.
Examples
Transaction In a TRY/CATCH
This will rollback both inserts due to an invalid datetime:
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, GETDATE(), 1)
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, 'not a date', 1)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
THROW
ROLLBACK TRANSACTION
END CATCH
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, GETDATE(), 1)
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, GETDATE(), 1)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
THROW
ROLLBACK TRANSACTION
END CATCH
https://riptutorial.com/ 186
Chapter 60: UNION / UNION ALL
Introduction
UNION keyword in SQL is used to combine to SELECT statement results with out any duplicate.
In order to use UNION and combine results both SELECT statement should have same number of
column with same data type in same order, but the length of column can be different.
Syntax
Remarks
UNION and UNION ALL clauses combine the result-set of two or more identically structured SELECT
statements into a single result / table.
Both the column count and column types for each query have to match in order for a UNION / UNION
ALL to work.
The difference between a UNION and a UNION ALL query is that the UNION clause will remove any
duplicate rows in the result where the UNION ALL will not.
This distinct removal of records can significantly slow queries even if there are no distinct rows to
be removed because of this if you know there wont be any duplicates (or don't care) always
default to UNION ALL for a more optimised query.
Examples
Basic UNION ALL query
PersonID INT,
LastName VARCHAR(30),
FirstName VARCHAR(30),
Position VARCHAR(30)
https://riptutorial.com/ 187
);
Let's say we want to extract the names of all the managers from our departments.
Using a UNIONwe can get all the employees from both HR and Finance departments, which hold
the position of a manager
SELECT
FirstName, LastName
FROM
HR_EMPLOYEES
WHERE
Position = 'manager'
UNION ALL
SELECT
FirstName, LastName
FROM
FINANCE_EMPLOYEES
WHERE
Position = 'manager'
The UNIONstatement removes duplicate rows from the query results. Since it is possible to have
people having the same Name and position in both departments we are using UNION ALL, in order
not to remove duplicates.
If you want to use an alias for each output column, you can just put them in the first select
statement, as follows:
SELECT
FirstName as 'First Name', LastName as 'Last Name'
FROM
HR_EMPLOYEES
WHERE
Position = 'manager'
UNION ALL
SELECT
FirstName, LastName
FROM
FINANCE_EMPLOYEES
WHERE
Position = 'manager'
In simple terms:
•UNION joins 2 result sets while removing duplicates from the result set
•UNION ALL joins 2 result sets without attempting to remove duplicates
One mistake many people make is to use a UNION when they do not need to have the
duplicates removed. The additional performance cost against large results sets can be
very significant.
https://riptutorial.com/ 188
When you might need UNION
Suppose you need to filter a table against 2 different attributes, and you have created separate
non-clustered indexes for each column. A UNION enables you to leverage both indexes while still
preventing duplicates.
This simplifies your performance tuning since only simple indexes are needed to perform these
queries optimally. You may even be able to get by with quite a bit fewer non-clustered indexes
improving overall write performance against the source table as well.
When you might need UNION ALL
Suppose you still need to filter a table against 2 attributes, but you do not need to filter duplicate
records (either because it doesn't matter or your data wouldn't produce any duplicates during the
union due to your data model design).
This is especially useful when creating Views that join data that is designed to be physically
partitioned across multiple tables (maybe for performance reasons, but still wants to roll-up
records). Since the data is already split, having the database engine remove duplicates adds no
value and just adds additional processing time to the queries.
Read UNION / UNION ALL online: https://riptutorial.com/sql/topic/349/union---union-all
https://riptutorial.com/ 189
Chapter 61: UPDATE
Syntax
•UPDATE table
SET column_name = value, column_name2 = value_2, ..., column_name_n = value_n
WHERE condition (logical operator condition_n)
Examples
Updating All Rows
This example uses the Cars Table from the Example Databases.
UPDATE Cars
SET Status = 'READY'
This statement will set the 'status' column of all rows of the 'Cars' table to "READY" because it
does not have a WHERE clause to filter the set of rows.
Updating Specified Rows
This example uses the Cars Table from the Example Databases.
UPDATE
Cars
SET Status = 'READY'
WHERE
Id = 4
This statement will set the status of the row of 'Cars' with id 4 to "READY".
WHERE clause contains a logical expression which is evaluated for each row. If a row fulfills the
criteria, its value is updated. Otherwise, a row remains unchanged.
Modifying existing values
This example uses the Cars Table from the Example Databases.
UPDATE Cars
SET TotalCost = TotalCost + 100
WHERE Id = 3 or Id = 4
Update operations can include current values in the updated row. In this simple example the
TotalCost is incremented by 100 for two rows:
https://riptutorial.com/ 190
•The TotalCost of Car #3 is increased from 100 to 200
•The TotalCost of Car #4 is increased from 1254 to 1354
A column's new value may be derived from its previous value or from any other column's value in
the same table or a joined table.
UPDATE with data from another table
The examples below fill in a PhoneNumber for any Employee who is also a Customer and currently
does not have a phone number set in the Employees Table.
(These examples use the Employees and Customers tables from the Example Databases.)
Standard SQL
Update using a correlated subquery:
UPDATE
Employees
SET PhoneNumber =
(SELECT
c.PhoneNumber
FROM
Customers c
WHERE
c.FName = Employees.FName
AND c.LName = Employees.LName)
WHERE Employees.PhoneNumber IS NULL
SQL:2003
Update using MERGE:
MERGE INTO
Employees e
USING
Customers c
e.FName = c.Fname
ON
AND e.LName = c.LName
AND e.PhoneNumber IS NULL
SQL Server
Update using INNER JOIN:
https://riptutorial.com/ 191
UPDATE
Employees
SET PhoneNumber = c.PhoneNumber
FROM
Employees e
INNER JOIN Customers c
ON e.FName = c.FName
AND e.LName = c.LName
WHERE
PhoneNumber IS NULL
https://riptutorial.com/ 192
Chapter 62: Views
Examples
Simple views
A view can filter some rows from the base table or project only some columns from it:
Complex views
A view can be a really complex query(aggregations, joins, subqueries, etc). Just be sure you add
column names for everything you select:
SELECT *
FROM dept_income;
DepartmentName TotalSalary
HR 1900
Sales 600
https://riptutorial.com/ 193
Chapter 63: Window Functions
Examples
Adding the total rows selected to every row
id name Ttl_Rows
1 example 5
2 foo 5
3 bar 5
4 baz 5
5 quux 5
Instead of using two queries to get a count then the line, you can use an aggregate as a window
function and use the full result set as the window.
This can be used as a base for further calculation without the complexity of extra self joins.
Table items
id 1 name tag
2 example unique_tag
foo
42 bar simple
simple
3 baz hello
51 quux world
I'd like to get all those lines and know if a tag is used by other lines
SELECT id, name, tag, COUNT(*) OVER (PARTITION BY tag) > 1 AS flag FROM items
https://riptutorial.com/ 194
The result will be:
In case your database doesn't have OVER and PARTITION you can use this to produce the same
result:
SELECT id, name, tag, (SELECT COUNT(tag) FROM items B WHERE tag = A.tag) > 1 AS flag FROM
items A
date amount
2016-03-12 200
2016-03-11 -50
2016-03-14 100
2016-03-15 100
2016-03-10 -250
https://riptutorial.com/ 195
date 2016- amount running
03-14 100 0
15
Getting the N most recent rows over multiple grouping
User_ID Completion_Date
1 2016-07-20
1 2016-07-21
2 2016-07-20
2 2016-07-21
2 2016-07-22
;with CTE as
(SELECT *,
ROW_NUMBER() OVER (PARTITION BY User_ID
ORDER BY Completion_Date DESC) Row_Num
FROM Data)
SELECT * FORM CTE WHERE Row_Num <= n
Using n=1, you'll get the one most recent row per user_id:
1 2016-07-21 1
2 2016-07-22 1
https://riptutorial.com/ 196
ID STATUS STATUS_TIME STATUS_BY
Items identified by ID values must move from STATUS 'ONE' to 'TWO' to 'THREE' in sequence,
without skipping statuses. The problem is to find users (STATUS_BY) values who violate the rule and
move from 'ONE' immediately to 'THREE'.
The LAG() analytical function helps to solve the problem by returning for each row the value in the
preceding row:
SELECT * FROM (
SELECT
t.*,
LAG(status) OVER (PARTITION BY id ORDER BY status_time) AS prev_status
FROM test t
) t1 WHERE status = 'THREE' AND prev_status != 'TWO'
In case your database doesn't have LAG() you can use this to produce the same result:
https://riptutorial.com/ 197
Chapter 64: XML
Examples
Query from XML Data Type
Results
https://riptutorial.com/ 198
Credits
S.
No Chapters Contributors
AND & OR
3 guiguiblitz
Operators
Cascading Delete
4 Stefan Steiger
https://riptutorial.com/ 199
DROP or DELETE
15 Abhilash R Vankayala, John Odom
Database
DROP Table
16 CL., Joel, KIRAN KUMAR MATAM, Stu
9 EXPLAIN and
21 Simulant
DESCRIBE
2
Filter results using
Arulkumar, Bostjan, CL., Community, Franck Dernoncourt, H.
0 WHERE and
22 Pauwelyn, Jon Chan, Jon Ericson, juergen d, Matas
HAVING
Vaitkevicius, Mureinik, Phrancis, Tot Zam
Finding Duplicates
on a Column Subset
23 Darrel Lee, mnoronha
with Detail
Foreign Keys
24 CL., Harjot, Yehuda Shapira
ashja99, CL., Florin Ghita, Ian Kenney, Imran Ali Khan, Jon
Functions Chan, juergen d, KIRAN KUMAR MATAM, Mark Stewart,
25
(Aggregate) Maverick, Nathan, omini data, Peter K, Reboot, Tot Zam,
William Ledbetter, winseybash, Алексей Неудачин
CL., omini data
26 Functions (Analytic)
Functions
27 CL., Kewin Björk Nielsen, Mark Stewart
(Scalar/Single Row)
GRANT and
28 REVOKE RamenChef, user2314737
https://riptutorial.com/ 200
31 IN clause CL., juergen d, walid, Zaga
dmfay
3 Materialized Views
Abhilash R Vankayala, CL., Kyle Hale, SQLFox, Zoyd
7 MERGE
Bart Schuijt, CL., dd4711, Devmati Wadikar, Phrancis, Saroj
3 Sasmal, StanislavL, walid, ypercube
39 NULL
Andi Mohr, CL., Cristian Abelleira, Jaydles, mithra chintha,
8 nazark, Özgür Öztürk, Parado, Phrancis, Wolfgang
40 ORDER BY a1ex07, Gallus, Ryan Rockey, ypercube
https://riptutorial.com/ 201
, Dean Parker, DeepSpace, Dipesh Poudel, Dror, Durgpal Singh
, Epodax, Eric VB, FH-Inway, Florin Ghita, FlyingPiMonster,
Franck Dernoncourt, geeksal, George Bailey, Hari K M,
HoangHieu, iliketocode, Imran Ali Khan, Inca, Jared Hooper,
Jaydles, John Odom, John Slegers, Jojodmo, JonH, Kapep,
KartikKannapur, Lankymart, Mark Iannucci, Mark Perera, Mark
Wojciechowicz, Matas Vaitkevicius, Matt, Matt S, Mattew Whitt,
Matthew Moisen, MegaTom, Mihai-Daniel Virna, Mureinik,
mustaccio, mxmissile, Oded, Ojen, onedaywhen, Paul Bambury,
penderi, Peter Gordon, Prateek, Praveen Tiwari, Přemysl
Šťastný, Preuk, Racil Hilan, Robert Columbia, Ronnie Wang,
Ryan, Saroj Sasmal, Shiva, SommerEngineering, sqluser, stark,
sunkuet02, ThisIsImpossible, Timothy, user1336087,
user1605665, waqasahmed, wintersolider, WMios, xQbert, Yury
Fedorov, Zahiro Mor, zedfoxus
John Smith
46 Sequence SKIP
TAKE
47 CL., Karl Blacquiere, Matas Vaitkevicius, RamenChef
(Pagination)
SQL CURSOR
48 Stefan Steiger
SQL Group By vs
49 Distinct carlosb
57 Triggers
https://riptutorial.com/ 202
Steve Nouri
https://riptutorial.com/ 203