Binary data is not getting stored in SQLite, returns null - sqlite

Printing out the data gives me:
\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00\x84\x00\t\x06\x07\x13\x13\x12\x15\x13\x13\x13\x16\x16\x15\x17\x19\x1a\x1b\x17\x16\x18\x18
So the binary data is present. However, when I try inserting the value with this code:
for i in check_row:
if i[0] == 0:
db.execute("INSERT INTO profiles (profile_id, city, country, interest, bio, picture) VALUES (:user, :city, :country, :interest, :bio, :picture)",
[user, city, country, interest, bio, empPicture])
conn.commit()
flash("profile completed")
return redirect("/")
else:
db.execute("UPDATE profiles SET city = :city, country = :country, interest = :interest, bio = :bio, picture = :picture WHERE profile_id = :profile_id",
[city, country, interest, bio, user, empPicture])
conn.commit()
flash("profile updated")
return redirect("/profile")
empPicture is the variable holding the binary data. This returns no error however, data never gets inputted into the picture BLOB column, it just shows NULL and prints out None when ran.
This is my table:
CREATE TABLE "profiles" ( "profile_id" INTEGER, "city" TEXT VARCHAR(255), "country" TEXT VARCHAR(255), "interest" TEXT VARCHAR(255), "bio" TEXT VARCHAR(255), "picture" BLOB )

I believe you have to wrap your insert into sqlite3.Binary as follows:
db.execute("INSERT INTO profiles (profile_id, city, country, interest, bio, picture) VALUES (:user, :city, :country, :interest, :bio, :picture)",
[user, city, country, interest, bio, sqlite3.Binary(empPicture)])
conn.commit()
More details can be found here.

Related

SQLite: trigger to check newly inserted row against limits in another table

I have a database with the following schema:
Sensors (
ID INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
SITE_ID INTEGER REFERENCES Sites (ID)
NOT NULL,
NAME TEXT UNIQUE
NOT NULL
);
Sites (
ID INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
NAME TEXT UNIQUE
NOT NULL
);
Data (
SENSOR_ID INTEGER REFERENCES Sensors (ID)
NOT NULL,
COUNT INTEGER NOT NULL,
TIME DATETIME NOT NULL,
TYPE TEXT NOT NULL,
VALUE REAL NOT NULL,
PRIMARY KEY (
SENSOR_ID,
COUNT,
TIME,
TYPE
)
);
Limits (
SITE_ID INTEGER REFERENCES Sites (ID)
NOT NULL,
TYPE TEXT NOT NULL,
HIGH REAL NOT NULL,
LOW REAL NOT NULL,
PRIMARY KEY (
SITE_ID,
TYPE
)
);
Data contains all the data for all sensors and sites, Data has a few different types. The limits have a row for each type of data for each of the sites. I want to create a table identical to Data (called Warnings) containing only the rows where the value lies outside of the limits in Limit.
I want to do this with a trigger because the limits can change and the rows are added to data sporadically.
Here's my best attempt so far:
CREATE TRIGGER VALUE_OUT_OF_RANGE
AFTER INSERT
ON Data
WHEN NEW.VALUE < (SELECT Limits.LOW FROM Limits INNER JOIN Sensors ON (Sensors.SITE_ID = Limits.SITE_ID) WHERE (Sensors.ID = NEW.SENSOR_ID AND Limits.TYPE = NEW.TYPE))
BEGIN
INSERT INTO Warnings(SENSOR_ID, COUNT, TIME, TYPE, VALUE) VALUES(NEW.SENSOR_ID, NEW.COUNT, NEW.TIME, NEW.TYPE, NEW.VALUE);
END;
In my attempt I've only checked against the lower limit, in the final trigger I would like to check that the value is between the LOW and HIGH limits.
I've tried the Select statement seperately and I get the data that I am looking for.
Any help or suggestion is greatly appreciated.
I managed to find a solution that works.
Posting it in case it helps anyone.
CREATE TRIGGER VALUE_OUT_OF_RANGE
AFTER INSERT
ON Data
FOR EACH ROW
WHEN NEW.VALUE < (
SELECT Limits.LOW
FROM Limits
JOIN
Sensors ON (Sensors.SITE_ID = Limits.SITE_ID)
WHERE (Sensors.ID = NEW.Sensor_ID AND
Limits.TYPE = NEW.TYPE)
LIMIT 1
)
OR
NEW.VALUE > (
SELECT Limits.HIGH
FROM Limits
JOIN
Sensors ON (Sensors.SITE_ID = Limits.SITE_ID)
WHERE (Sensors.ID = NEW.Sensor_ID AND
Limits.TYPE = NEW.TYPE)
LIMIT 1
)
BEGIN
INSERT INTO Warnings (
SENSOR_ID,
COUNT,
TIME,
TYPE,
VALUE
)
VALUES (
NEW.SENSOR_ID,
NEW.COUNT,
NEW.TIME,
NEW.TYPE,
NEW.VALUE
);
END;

How to use a % wild card in a query to an sqlite3 table with user input where clause

I have written a query which allows a user to search a table in an sqlite3 database with any of 4 different fields. It will only return data if what the user enters is an exact match is there a way to put a wild card in for each field. Code below
import sqlite3
conn = sqlite3.connect("lucyartists.db")
cursor = conn.cursor()
#Get user input
print ('Search for an Artist')
print ('You can search by Name, DOB, Movement or Description')
print ('')
name = input("Enter Artists Name: ")
dob = input("Enter Date of Birth: ")
movement = input("Enter Movemment: ")
description = input ("Enter Description: ")
#query database with user input
sql = ("select name, dob, movement, description from artists where name like (?) or dob like (?) or movement like (?) or description like (?)")
values = (name, dob, movement, description)
#Run query
cursor.execute(sql, values)
result = cursor.fetchall()
#print results without quotes and comma separated
print()
print('RESULTS')
for r in result:
print()
print("{}, {}, {}, {}".format(r[0], r[1], r[2], r[3]))

u-sql script to search for a string then Groupby that string and get the count of distinct files

I am quite new to u-sql, trying to solve
str1=\global\europe\Moscow\12345\File1.txt
str2=\global.bee.com\europe\Moscow\12345\File1.txt
str3=\global\europe\amsterdam\54321\File1.Rvt
str4=\global.bee.com\europe\amsterdam\12345\File1.Rvt
case1:
how do i get just "\europe\Moscow\12345\File1.txt" from the strings variable str1 & str2, i want to just take ("\europe\Moscow\12345\File1.txt") from str1 and str2 then "Groupby(\global\europe\Moscow\12345)" and take the count of distinct files from the path (""\europe\Moscow\12345\")
so the output would be something like this:
distinct_filesby_Location_Date
to solve the above case i tried the below u-sql code but not quite sure whether i am writing the right script or not:
#inArray = SELECT new SQL.ARRAY<string>(
filepath.Contains("\\europe")) AS path
FROM #t;
#filesbyloc =
SELECT [ID],
path.Trim() AS path1
FROM #inArray
CROSS APPLY
EXPLODE(path1) AS r(location);
OUTPUT #filesbyloc
TO "/Outputs/distinctfilesbylocation.tsv"
USING Outputters.Tsv();
any help would you greatly appreciated.
One approach to this is to put all the strings you want to work with in a file, eg strings.txt and save it in your U-SQL input folder. Also have a file with the cities in you want to match, eg cities.txt. Then try the following U-SQL script:
#input =
EXTRACT filepath string
FROM "/input/strings.txt"
USING Extractors.Tsv();
// Give the strings a row-number
#input =
SELECT ROW_NUMBER() OVER() AS rn,
filepath
FROM #input;
// Get the cities
#cities =
EXTRACT city string
FROM "/input/cities.txt"
USING Extractors.Tsv();
// Ensure there is a lower-case version of city for matching / joining
#cities =
SELECT city,
city.ToLower() AS lowercase_city
FROM #cities;
// Explode the filepath into separate rows
#working =
SELECT rn,
new SQL.ARRAY<string>(filepath.Split('\\')) AS pathElement
FROM #input AS i;
// Explode the filepath string, also changing to lower case
#working =
SELECT rn,
x.pathElement.ToLower() AS pathElement
FROM #working AS i
CROSS APPLY
EXPLODE(pathElement) AS x(pathElement);
// Create the output query, joining on lower case city name, display, normal case name
#output =
SELECT c.city,
COUNT( * ) AS records
FROM #working AS w
INNER JOIN
#cities AS c
ON w.pathElement == c.lowercase_city
GROUP BY c.city;
// Output the result
OUTPUT #output TO "/output/output.txt"
USING Outputters.Tsv();
//OUTPUT #working TO "/output/output2.txt"
//USING Outputters.Tsv();
My results:
HTH
Taking the liberty to format your input file as TSV file, and not knowing all the column semantics, here is a way to write your query. Please note that I made the assumptions as provided in the comments.
#d =
EXTRACT path string,
user string,
num1 int,
num2 int,
start_date string,
end_date string,
flag string,
year int,
s string,
another_date string
FROM #"\users\temp\citypaths.txt"
USING Extractors.Tsv(encoding: Encoding.Unicode);
// I assume that you have only one DateTime format culture in your file.
// If it becomes dependent on the region or city as expressed in the path, you need to add a lookup.
#d =
SELECT new SqlArray<string>(path.Split('\\')) AS steps,
DateTime.Parse(end_date, new CultureInfo("fr-FR", false)).Date.ToString("yyyy-MM-dd") AS end_date
FROM #d;
// This assumes your paths have a fixed formatting/mapping into the city
#d =
SELECT steps[4].ToLowerInvariant() AS city,
end_date
FROM #d;
#res =
SELECT city,
end_date,
COUNT( * ) AS count
FROM #d
GROUP BY city,
end_date;
OUTPUT #res
TO "/output/result.csv"
USING Outputters.Csv();
// Now let's pivot the date and count.
OUTPUT #res2
TO "/output/res2.csv"
USING Outputters.Csv();
#res2 =
SELECT city, MAP_AGG(end_date, count) AS date_count
FROM #res
GROUP BY city;
// This assumes you know exactly with dates you are looking for. Otherwise keep it in the first file representation.
#res2 =
SELECT city,
date_count["2016-11-21"]AS [2016-11-21],
date_count["2016-11-22"]AS [2016-11-22]
FROM #res2;
UPDATE AFTER RECEIVING SOME EXAMPLE DATA IN PRIVATE EMAIL:
Based on the data you sent me (after the extraction and counting of the cities that you either could do with the join as outlined in Bob's answer where you need to know your cities in advance, or with the taking the string from the city location in the path as in my example, where you do not need to know the cities in advance), you want to pivot the rowset city, count, date into the rowset date, city1, city2, ... were each row contains the date and the counts for each city.
You could easily adjust my example above by changing the calculations of #res2 in the following way:
// Now let's pivot the city and count.
#res2 = SELECT end_date, MAP_AGG(city, count) AS city_count
FROM #res
GROUP BY end_date;
// This assumes you know exactly with cities you are looking for. Otherwise keep it in the first file representation or use a script generation (see below).
#res2 =
SELECT end_date,
city_count["istanbul"]AS istanbul,
city_count["midlands"]AS midlands,
city_count["belfast"] AS belfast,
city_count["acoustics"] AS acoustics,
city_count["amsterdam"] AS amsterdam
FROM #res2;
Note that as in my example, you will need to enumerate all cities in the pivot statement by looking it up in the SQL.MAP column. If that is not known apriori, you will have to first submit a script that creates the script for you. For example, assuming your city, count, date rowset is in a file (or you could just duplicate the statements to generate the rowset in the generation script and the generated script), you could write it as the following script. Then take the result and submit it as the actual processing script.
// Get the rowset (could also be the actual calculation from the original file
#in = EXTRACT city string, count int?, date string
FROM "/users/temp/Revit_Last2Months_Results.tsv"
USING Extractors.Tsv();
// Generate the statements for the preparation of the data before the pivot
#stmts = SELECT * FROM (VALUES
( "#s1", "EXTRACT city string, count int?, date string FROM \"/users/temp/Revit_Last2Months_Results.tsv\" USING Extractors.Tsv();"),
( "#s2", "SELECT date, MAP_AGG(city, count) AS city_count FROM #s1 GROUP BY date;" )
) AS T( stmt_name, stmt);
// Now generate the statement doing the pivot
#cities = SELECT DISTINCT city FROM #in2;
#pivots =
SELECT "#s3" AS stmt_name, "SELECT date, "+String.Join(", ", ARRAY_AGG("city_count[\""+city+"\"] AS ["+city+"]"))+ " FROM #s2;" AS stmt
FROM #cities;
// Now generate the OUTPUT statement after the pivot. Note that the OUTPUT does not have a statement name.
#output =
SELECT "OUTPUT #s3 TO \"/output/pivot_gen.tsv\" USING Outputters.Tsv();" AS stmt
FROM (VALUES(1)) AS T(x);
// Now put the statements into one rowset. Note that null are ordering high in U-SQL
#result =
SELECT stmt_name, "=" AS assign, stmt FROM #stmts
UNION ALL SELECT stmt_name, "=" AS assign, stmt FROM #pivots
UNION ALL SELECT (string) null AS stmt_name, (string) null AS assign, stmt FROM #output;
// Now output the statements in order of the stmt_name
OUTPUT #result
TO "/pivot.usql"
ORDER BY stmt_name
USING Outputters.Text(delimiter:' ', quoting:false);
Now download the file and submit it.

How can I properly handle an sqlite table self reference?

I have created an sqlite db for a small cattle herd.
CREATE TABLE Animals
(
animal_id PRIMARY KEY,
animal_name CHAR(15) NULL,
date_born DATE NULL,
f_parent REFERENCES Animals (animal_id) NULL,
m_parent REFERENCES Animals (animal_id) NULL,
date_purchased DATE NULL,
registered BIT NOT NULL,
gender CHAR(1) NOT NULL CHECK(gender IN ("M","F")),
breed INTEGER NOT NULL REFERENCES breed (breed_id)
);
CREATE TABLE termination (term_key INTEGER PRIMARY KEY, animal_id INTEGER, term_date DATE, sold BIT, price SMALLMONEY, comp_market_price SMALLMONEY, comp_market_tier TEXT);
I have this statement:
SELECT a1.animal_id, a1.animal_name, a1.f_parent, t1.term_date, t1.price, t1.comp_market_price, t1.comp_market_tier
FROM Animals AS a1, termination AS t1
WHERE a1.animal_id = t1.animal_id
AND a1.f_parent NOT NULL;
results are:
id#|'animal name'|'parent id#'|date sold ...
15|some name|4|2014-05-26 ...
...
which is correct and what I wanted except that in place of 'parent id#' I want the parent's name. The parent id# is a key in the same table as the offspring (as you see from my create statement above), but I can't figure out how to deal with this self-reference. I know the issue is rather common, and I've tried view tables, multiple joins, etc. to no avail. Please show code snippet of how I can print the same results showing the parents name in place of parent id#/key no.
thank you very much!
Something like this maybe?
select a.animal_id, a.animal_name,
(select animal_name
from animals
where a.f_parent = animal_id) as parent,
t.term_date, t.price, t.comp_market_price, t.comp_market_tier
from animals as a, termination as t using(animal_id)
where a.f_parent not null;
or this? (better execution plan)
select a.animal_id as id, a.animal_name as name,f.animal_name as mother,
t.term_date, t.price, t.comp_market_price, t.comp_market_tier
from animals as a, termination as t using(animal_id),
animals f
where a.f_parent = f.animal_id
and a.f_parent is not null;

Decode returning multiple rows

I have a business case where in a table I may have a specific value or it will have value as 'ALL'. While I query the table if particular input matches I need that particular record. If its not matching then entry with ALL should be considered and returned.
Here is the case that you have try at your end to replicate the issues.
CREATE TABLE lookup_value (
country VARCHAR2(2) NOT NULL,
department VARCHAR2(30) NOT NULL,
problem_code VARCHAR2(30),
disposition VARCHAR2(30));
INSERT INTO lookup_value VALUES ('US','SALES','P0044','EXCHANGE')
INSERT INTO lookup_value VALUES ('US','SALES','ALL','EXCHANGE')
INSERT INTO lookup_value VALUES ('US','SALES','P0020','ALL')
INSERT INTO lookup_value VALUES ('US','SALES','ALL','ALL')
INSERT INTO lookup_value VALUES ('US','OPERATIONS','P0044','ACKNOELEDGE')
INSERT INTO lookup_value VALUES ('US','OPERATIONS','ALL', 'ALL')
SELECT *
FROM lookup_value
WHERE country = 'US'
AND department = 'SALES'
AND problem_code = DECODE (:problem, problem_code, :problem, 'ALL')
AND disposition = DECODE (:disp, disposition, :disp, 'ALL')
If I run the above query passing problem_code = P0044 and disposition = 'EXCHANGE', it returns me 3 rows, where as I need only one.
COUNTRY DEPARTMENT PROBLEM_CODE DISPOSITION
-----------------------------------------------------------
US SALES P0044 EXCHANGE
US SALES ALL EXCHANGE
US SALES ALL ALL
Regards
Tauseef

Resources