BASH, passing variables to a string for sqlite - bash

Ive hit a dead end trying to pass variables created in bash to a sqlite command string.Below you can see I am trying to write the artist_id (foreign key) into the songs table in artist_id. I can retrieve th artist_id field fine from the artists table. When I try to create a new record in the songs table with the variable $artist_id, I get an error;
Error: FOREIGN KEY constraint failed
Its definitely the correct key, 4 in this case, but sqlite doesn't seem to be accepting it so I think it may be a formatting issue? I tried removing quotes, adding '..etc. but no joy, any ideas?
artistcheck=$(sqlite3 "$dbFile" "$forkey SELECT EXISTS(SELECT 1 FROM artists WHERE artist_name='${ARRAY[2]}' LIMIT 1);")
if [ "$artistcheck" -eq 1 ]; then
artistid=$(sqlite3 "$dbFile" "$forkey SELECT artist_id FROM artists WHERE artist_name='${ARRAY[2]}';")
echo "Yep, "${ARRAY[2]}" exists and the id is $artistid."
else
echo "Nope, "${ARRAY[2]}" doesnt exist"
sqlite3 "$dbFile" "$forkey INSERT INTO artists (artist_name) VALUES ('${ARRAY[2]}');"
artistid=$(sqlite3 "$dbFile" "$forkey SELECT artist_id FROM artists WHERE artist_name='${ARRAY[2]}';")
echo "New Artist created. Name: ${ARRAY[2]} and ID is $artistid."
fi
songcheck=$(sqlite3 "$dbFile" "$forkey SELECT EXISTS(SELECT 1 FROM songs WHERE song_name='${ARRAY[1]}' AND artist_id='$artistid' LIMIT 1);")
if [ "$songcheck" -eq 1 ]; then
songid=$(sqlite3 "$dbFile" "$forkey SELECT song_id FROM songs WHERE song_name='${ARRAY[1]}' AND artist_id='$artistid';")
echo "Yep, "${ARRAY[1]}" exists and the song ID is $songid and the artist id is $artistid."
else
echo "Nope, "${ARRAY[1]}" doesnt exist"
sqlite3 "$dbFile" "$forkey INSERT INTO songs (artist_id, song_name) VALUES ('$artist_id','${ARRAY[2]}');"
songid=$(sqlite3 "$dbFile" "$forkey SELECT song_id FROM songs WHERE song_name='${ARRAY[1]}' AND artist_id='$artist_id';")
echo "New Song created. Name: ${ARRAY[1]} and song ID is $songid and the artist id is $artistid."
fi

Mixed up the variable $artistid with the field 'artist_id' in the sql statement. 4th line from the bottom I believe. Moral: use meaningful variable names and lay off the caffeine.

Related

Query returns 0, but my conditional statement isn't recognizing it as a 0

My Bash script uses SQLite to store data. I'm comparing id's (column jid) from table tester for which id's are in table test2:
sqlite3 jail.db "SELECT jid FROM tester" | while read jid; do
if sqlite3 jail.db "select exists(select 1 from test2 where jid=$jid limit 1)"; then
echo "i found it"
else
echo "i did not find it"
fi
done
Going through id's query returns 0 or 1, but my Bash script executes the 1 part of If/then/else regardless:
0
i found it
0
i found it
0
i found it
0
i found it
1
i found it
1
i found it
1
i found it
I guess you are looking for a left outer join, something like this
for r in $(sqlite3 jail.db 'select case when test2.jid != "" then 1 else 0 end from tester left outer join test2 on tester.jid = test2.jid;'); do
if [[ "$r" == 1 ]]; then
echo "i found it"
else
echo "i did not find it"
fi
done
notice the use of $() to get the output of the command not its exit value.

generate file from bash script

I have to generate a file.sql file, in which I want to hold some DDL statements.
Firstly it should create a database user, schema and grant some permissions. Then it should make copyes of some tables into newly created schema. Table names I hold in bash array variable. Number of tables in array may vary.
I cannot make one cat > file.sql < EOF ... EOF block to do that, because I need to generate CREATE TABLE and ALTER TABLE commands.. depends on the table count.
I made a generate.sh script with variables and three bash functions:
TABLES=( "table_one" "table_two" "table_three" "table_four" "table_five")
SOURCE_SCHEMA="src"
TARGET_SCHEMA="tgt"
FILE=file.sql
function create_prepare_sql_v1 {
cat > $FILE << EOF_SQL_V1
...here goes create user/schema and grant statements...
EOF_SQL_V1
function create_prepare_sql_v2 {
count=1
for table in ${!TABLES[#]}; do
( echo -e "CREATE TABLE $SOURCE_SCHEMA.${TABLES[$table]} AS TABLE $TARGET_SCHEMA.${TABLES[$table]};" \
"\nALTER TABLE $SOURCE_SCHEMA.${TABLES[$table]} ADD PRIMARY KEY(id);" \
"\nINSERT INTO $SOURCE_SCHEMA.temp VALUES ("$count", '"$TARGET_SCHEMA"', '"${TABLES[$table]}"');" ) >> $FILE
((count++))
done
function create_prepare_sql_v3 {
cat >> $FILE << 'EOF_SQL_V3'
...here I put my custom PL/pgSQL functions...
EOF_SQL_V3
When I execute the functions and I check that file.sql has allprevious data by adding and removing step#_done strings. When all done, I remove step_3_done string.
It works but seems, that this is a very weak solution.
create_prepare_sql_v1 && echo "step1_done" >> $FILE || exit 1
create_prepare_sql_v2 && sed -i 's/step1_done/step2_done/' $FILE || exit 1
create_prepare_sql_v3 && sed -i 's/step2_done/step3_done/' $FILE || exit 1
if ! fgrep -q 'step3_done' $FILE ; then
echo "Something went wrong. Exiting.."
exit 1
fi
sed -i '/step3_done/d' $FILE
echo "All good."
After generation the file.sql should be something like that:
\connect dbname
CREATE USER u_user WITH PASSWORD 'blah';
CREATE SCHEMA IF NOT EXISTS src AUTHORIZATION u_user;
GRANT USAGE ON SCHEMA src TO u_user;
CREATE TABLE src.temp (
id INTEGER PRIMARY KEY,
schema_name VARCHAR(100),
table_name VARCHAR(100),
truncated BOOLEAN DEFAULT false
);
CREATE TABLE src.table_one AS TABLE tgt.table_one;
ALTER TABLE src.table_one ADD PRIMARY KEY(id);
INSERT INTO src.temp VALUES (1, 'tgt', 'table_one');
CREATE TABLE src.table_two AS TABLE tgt.table_two;
ALTER TABLE src.table_two ADD PRIMARY KEY(id);
INSERT INTO src.temp VALUES (2, 'tgt', 'table_two');
CREATE TABLE src.table_three AS TABLE tgt.table_three;
ALTER TABLE src.table_three ADD PRIMARY KEY(id);
INSERT INTO src.temp VALUES (3, 'tgt', 'table_three');
etc
CREATE OR REPLACE FUNCTION ..
CREATE OR REPLACE FUNCTION ..
CREATE OR REPLACE FUNCTION ..
If it was only sql statements with constant number of tables, there would be no problem to do that with one cat > $FILE << EOF <some_code> EOF block...
Can you plese offer a better solution?
Thanks!

If loop not working properly

In my script i execute correctly when first time in the if loop execute after the third time of execution its not working properly .what can i do is any mistake ah...? please fix my issue...?in the script i gave the value for customer name as ABC then again i gave the ABC that time it ececute the if condition correctly,but i gave the third time as ABC its not working properly..!
#!/bin/bash
echo " --- Enter the Database name ---"
read databasename
echo " --- enter the table name --- "
read table_name
sqlite3 $databasename.db "DROP TABLE IF EXISTS $table_name;"
sqlite3 $databasename.db "CREATE TABLE IF NOT EXISTS $table_name(cus_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,cus_name TEXT NOT NULL UNIQUE ,cus_domain TEXT UNIQUE, cus_status TEXT NOT NULL,Port INTEGER NOT NULL);"
echo " --- Enter the total number of rows do you want ---"
read cus_count
echo "--- Enter the following details one by one---"
port_num=8080
for((i=1;i<=cus_count;i++))
do
echo "enter the $i customer details"
echo "---Enter the customer name---"
read c_name
customer=$(sqlite3 $databasename.db "select cus_name from $table_name")
if [[ "$port_num" == "$port_num" ]]; then
port_num=$(($port_num + 1))
fi
if [[ $c_name != $customer ]]
then
echo "---Enter the Status(Active/Inactive)---"
read c_status
c_domain="$c_name"
else
echo "---OOPS you entered customer name already available---"
echo "---Please enter new customer name---"
i=$(($i - 1))
fi
sqlite3 $databasename.db "INSERT OR IGNORE INTO $table_name (cus_name,cus_domain,cus_status, Port) VALUES(\"$c_name\",\"${c_domain,,}.com\",\"$c_status\",\"$port_num\") ;"
done
echo " --- Records from the $table_name ---"
sqlite3 $databasename.db "select * from $table_name;"
please refer to below on "bash script arithmetic operations"
http://tldp.org/LDP/abs/html/arithexp.html
or
http://tldp.org/LDP/abs/html/ops.html

unix shell script to check result of sql query

I have the code like this
v_use_xref_result=`sqlplus -s $UP <
Select Code_Desc
From Code_Detail
Where Code='UXLOC'
and CODE_TYPE='UXRF'
EOF`
if [ "$v_use_xref_result" == "Y" ]; then
echo "s" else
echo "n"
fi
when I query the same in sql developer I am getting the result as Y for this query Select Code_Desc From Code_Detail Where Code='UXLOC' and CODE_TYPE='UXRF' the datatype of Code_Desc is varchar
but I am unable to check in if condition. i am getting "n" as result for this script.
can anyone help me how to check it in if condition.
As written, the heredoc syntax in your script doesn't seem to be correct. Try saying:
v_use_xref_result=$(sqlplus -s $UP <<EOF
Select Code_Desc
From Code_Detail
Where Code='UXLOC'
and CODE_TYPE='UXRF'
EOF
)

Check if value within column exists, if not create the column

I need to check if one of the columns in my db contains specific value. If it doesn't I want to create that row with folowing values:
#!/bin/bash
#
MODEL=$1
if true (SELECT * FROM table.STATISTICS
WHERE MODEL = '$MODEL' )
do this (INSERT INTO table.STATISTICS('$MODEL',0,SYSDATE,0,SYSDATE,0); )
You could use a merge for this, run through SQL*Plus as a 'heredoc', so you don't have to do a separate count operation; the merge will do that for you effectively:
#!/bin/bash
MODEL=$1
sqlplus -s /nolog <<!EOF
connect user/pass
merge into statistics s
using (select '${MODEL}' as model, 0 as num1, sysdate as date1,
0 as num2, sysdate as date2 from dual) t
on (s.model = t.model)
when not matched then
insert (s.model, s.num1, s.date1, s.num2, s.date2)
values (t.model, t.num1, t.date1, t.num2, t.date2);
!EOF
But using your real column names, obviously. It's better to list them explicitly even for a plain insert.
get_count () {
sqlplus -s username/pass <<!
set heading off
set feedback off
set pages 0
select count(model) from statistics
where model='$MODEL';
!
}
count=$(get_count $1)
if [ "${count:-0}" -eq 0 ]; then
echo "its zero"
sqlplus -S username/pass << EOF
whenever sqlerror exit 1;
set echo on
set verify off
INSERT INTO table.STATISTICS VALUES('$MODEL',0,SYSDATE,0,SYSDATE,0);
exit;
EOF
fi

Resources