Helpful Resources
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit
Helpful Resources
SQL
Here we have provided some SQL notation that you might find helpful. Depending on your solution, you may not need to use all of these:
· A case statement allow you to express a conditional expression (similar to if/else).
● You can have a select statement with hardcoded values:
select *
from(values (1,'pie'),(2,'cake'),(3,'ice-cream'))as desserts(id, name);
● least and greatest can be used to find the minimum and maximum among a list of expressions respectively.
Date and Times in SQL
This assignment deals heavily with dates, times and timestamps. PostgreSQL offers an extensive set of functions and operators to work with these types. You can f ind
the full list here and we have included some of the notable ones below:
· You can extract the date portion of a time stamp by calling date.
csc343h-marinat=>select date(tTime)From Trip;
date
2023-05-03
(1 row)
· You can find the difference between two dates. The returned value is the number of days (integer).
csc343h-marinat=> select '2023-05-04'::date -'2023-05-03'::date as days;
days
1
(1 row)
· You can add an integer or an interval to a date.You can add an interval to a timestamp.
csc343h-marinat=> select '2023-05-04'::date + 1 as next day;
next day
2023-05-05
(1 row)
csc343h-marinat=>select '2023-05-04'::date + interval'l hour' as in an hour;
_ _
in an hour
_ _
2023-05-0401:00:00
(1 row)
csc343h-marinat=>select '2023-05-0408:00'::timestamp + interval'1 day 1 hour’
csc343h-marinat-> as tomorrow in an hour;
_ _ _
tomorrow in an hour
_ _ _
2023-05-0509:00:00
(1 row)
csc343h-marinat=>-- can't add an integer to a timestamp
csc343h-marinat=>select '2023-05-0408:00'::timestamp +5;
ERROR: operator does not exist:timestamp without time zone + integer
LINE 1:select '2023-05-0408:00'::timestamp +5;
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
· You can use the function overlap to check if two time periods overlap.
csc343h-marinat=>
csc343h-marinat->
csc343h-marinat->
overlaps
select('2023-04-0308:00'::timestamp,'2023-04-0413:00'::timestamp)
overlaps
('2023-04-0213:00’,’2023-04-0708:00');
t
(1 row)
● [NEW] You can make an interval using a given value for years, months, days, 钬②:
csc343h-marinat=>select make interval(years=>2,months=>3,days=>2,hours=>5);
make interval
2 years 3 mons 2 days 05:00:00
(1 row)
Psycopg2
psycopg2 is a Python library that provides an interface for manipulating and querying a PostgreSQL database.Psycopg22.9.3 is already installed on the teaching lab machines.
T his section briefly covers the basic use case of the library. The documentation also offers a tutorial that you might find helpful.
Making a connection
In order to issue commands to the database, you need to initialize a new database session. This can be done using the method connect that returns an instance of the connection class, which allows you to interact with the database.
import psycopg2 as pg
connection = pg.connect(
dbname='csc343h-marinat',user='',password=’’,
options="-c search path=waste wrangler"
The above will return a connection to the database, as well as set the search path to
waste wrangler.
Note you will need to change the value for dbname to your own personal
database: csc343h-(user name>.If you are working on your own machine, the default values for dbname,user and password are postgres, postgres, password respectively.
At the end of your session, you need to close that connection:
connection.close()
It is good practice to ALWAYS close the connection to the database. Consequently, you should make use of try/except blocks to ensure that the connection is always
closed even if an error occured.You can see an example of that in the main block of a2.py.
Cursors
Once you have established a connection to the database, you can use cursors to issue commands to the database and examine results of queries.
You can create as many cursors as you want from a single connection. Here, I have created two:
cursorl = connection.cursor()
cursor2 = connection.cursor()
You can use cursors to issue queries to the database:
>>># Get all trucks
>>> cursor1.execute("select * from Truck")
>>># rowcount attributes checks the number of rows in the result
>>> cursorl.rowcount
7
You can also use the cursor to inspect the result set of the issued query. You can do that by using one of the following:
· Using the fetchone method. This method will return the next row in the result
as a tuple, or None if the next row doesn钬撾exist.
>>> cursor1.execute("select * from Truck where tID = 1")
>>> cursor1.fetchone()
(1,'A’,23.0)
>>> cursor1.fetchone() # returns None since there are no more rows
· Using a for loop to iterate over the result.At each iteration, the current row will be returned as a tuple.
>>> cursor1.execute("select * from Truck where tID = 1")
>>> for row in cursorl:
print(row)
···
(1,'A', 23.0)
· Using fetchall that returns the entire result set as a list of tuples.
In the above examples, each row is returned as a tuple, where the item at the it h
index corresponds to the value of the ith attribute (column). Alternatively, each r ow
can be returned as a dictionary where the keys are the name of the columns, and
the values are the corresponding values of these columns as in this example .
Sanitizing user input
In most cases, you will be incorporating client钬楚input in your queries e.g., in a real application, the user will probably provide the value for the truck ID tID. It is
very important to sanitize your inputs to prevent against any SQL injection attacks. Luckily, psycopg2 provides a way for doing that:
· In your queries, you need to use the placeholder%s in place of where user input will be used. While this may look very similar to Python string
formatting, it is NOT the same. Also note that the placeholder %s is used in place of any value, irrespective of its type.
· In the call to execute, pass the values of these placeholders as a list, where their order in the list corresponds to their order of appearance in the SQL command
tid = 3
cursorl.execute("select * from Truck where tID =%s",[tid])
psycopg2 also provides a way to name your placeholders using the notation%
(name of placeholder)s. In that case, the second argument of execute is a dictionary that maps the name of each placeholder to its value.
tid = 3
cursor1.execute("select * from Truck where tID =%(tid)s", {'tid':tid})
Dealing with Exceptions
If an error occurs as a result of a SQL query/update, an Exception is raised. None of the cursors generated from this connection can be used, unless the connection is
rolled back. Rolling back the connection resets the state of the connection so it can accept more commands (more about that below).
>>># This raises an Exception because there is no Trucks relation
>>> cursor1.execute("select * from Trucks")
Traceback(most recent call last):
File "<stdin>",line 1,in <module>
psycopg2.errors.UndefinedTable:relation "trucks"does not exist
LINE 1: select * from Trucks
>>>#I can't use the cursor without rolling back the connection
>>> cursor1.execute("select * from Truck")
Traceback(most recent call last):
File "<stdin>",line 1,in <module>
psycopg2.errors.InFailedSqlTransaction: current transaction is aborted,
commands ignored until end of transaction block
>>># I can't even use the other cursor
>>> cursor2.execute("select * from Truck")
Traceback(most recent call last):
File "<stdin>",line l,in <module>
psycopg2.errors.InFailedSqlTransaction:current transaction is aborted,
commands ignored until end of transaction block
>>># and Not even a new cursor
>>> cursor3 = connection.cursor()
>>> cursor3.execute("select * from Truck")
Traceback(most recent call last):
File "<stdin>",line 1,in <module>
psycopg2.errors.InFailedSqlTransaction:current transaction is aborted,
commands ignored until end of transaction block
>>># Rolling back the connection allows me to use cursorl
>>>#(or any of the other cursors)
>>> connection.rollback()
>>> cursor1.execute("select * from Truck")
Committing to changes
Executing SQL DML commands is very similar to issuing queries:
1. you need to use the execute method of class cursor:
>>> |
cursor1.execute("insert |
into |
Truck values(10,'A’,50)") |
|
|
>>># |
For update,insert and |
delete |
commands,rowcount returns the |
number |
of |
>>># |
rows affected. |
|
|
|
|
>>> |
cursorl.rowcount |
|
|
|
|
Similar to executing queries, if the values used in the command are o btained from the user, you need to sanitize the input by making use of the second argument to
execute:
>>> cursorl.execute("insert into Truck values (%s,%s,%s)",[tid,truck type,capacity])
2. Unlike queries, calling execute will not actually change the database instance i.e., if you simultaneously open psql, you won钬撾see the new row we have
just added. In order to do that, you need to call the commit method of class
connection. Calling commit issues any uncommitted changes to the database i.e., once you call connection.commit(), the new row will be reflected in the database.
Commit and Rollback
You might have noticed that connection.commit()and connection. rollback() have exactly
the opposite functions from each other:
· connection.commit():commits any uncommitted changes to the database. · connection. rollback():undoes any uncommitted changes.
We usually use them in a try/except block as follows (the exact structure may vary):
# You can create the cursor here or under the try clause.
cursor = connection.cursor()
try:
# use the cursor here to query or manipulate the db.
# You can commit the changes here or under the else
# clause.
except pg.Error:
# An error occurred so we need to rollback the connection.
connection.rollback()
else:
# No error has occured.
finally:
# This code will always execute.
if cursor and not cursor.closed:
cursor.close()
Creating views
It is recommended to use views to break up your SQL commands into smaller more manageable pieces.
You can create views in psycopg2 using execute. However, note that cursor.rowcount will NOT return the actual number of rows contained in the view.
>>> cursor1.rowcount
-1
Python
Date and time in Python
The datetime module in Python provides classes for storing and manipulating dates
(date), times (time), and timestamps (datetime).
Here are some examples for using the different classes provided by the module:
>>> import datetime as dt
>>> dt.date(2023,5,4) # The date 2023-05-04
datetime.date(2023,5,4)
>>>dt.datetime(2023,5,4,13,10) # The timestamp 2023-05-041:10pm
datetime.datetime(2023,5,4,13,10)
>>> dt.time(8,2) # the time 8:02
datetime.time(8,2)
You can compare dates:
>>>dt.date(2023,5,4)<dt.date(2023,5,10)
True
You can also find the difference between dates:
>>>dt.date(2023,5,10)- dt.date(2023,5,4)
datetime.timedelta(days=6)
The returned value in the previous example is of type timedelta, which expresses the
difference between two different date, time or datetime instances. You can use
instances of the timedelta class to generate dates/time/time stamps that occur before/after a specific day/time/time stamp:
>>># A week after 2023-5- 10
>>>dt.date(2023,5,10)+dt.timedelta(days=7)
datetime.date(2023,5,17)
Note that date, time and datetime are immutable types i.e., they can钬圖be modified directly.
You can use date, time and datetime objects in the second argument of execute.
psycopg2 is able to map these types to the corresponding types used by Postgres.
2023-03-08