I am trying to do a kind of insert into select statement. I want to insert one column as standard and the second through a select. However this is not working:
queryString = "INSERT INTO Words (Word, SortedId) VALUES ('" + words[i] + "', (SELECT TOP 1 SortedId FROM SortedWords WHERE SortedWord = '" + sortWord(words[i]) + "'))";
SortedWords is already filled with data. But at the moment i get this error
{"There was an error parsing the query. [ Token line number = 1,Token line offset = 50,Token in error = SELECT ]"}
Note:
not sure if i need the TOP 1 bit or not, get error either way. But I obvs only want to insert one row.
Change your query to
queryString = "INSERT INTO Words (Word, SortedId) SELECT '" + words[i] + "', (SELECT TOP 1 SortedId FROM SortedWords WHERE SortedWord = '" + sortWord(words[i]) + "')";
Also, instead of concatenating strings to get your query, use parameters to avoid SQL injection.
Try next and better practice to use a SqlParameters:
INSERT INTO words
(word,
sortedid)
(SELECT TOP 1 #Word,
sortedid
FROM sortedwords
WHERE sortedword = #SortedWord)
And before execiting query create a parameters(C#)
//Assume you have a SqlCommand object(lets name it command)
command.Parameters.AddWithValue("#Word", words[i]);
command.Parameters.AddWithValue("#SortedWord", sortWord(words[i]));
Related
I am trying to write basic insert statement. I have columns with date type. In C# I get datetimepicker value and convert it to string, then try to insert it with to_date. But it shows ORA-01756: quoted string not properly terminated. I found question related to this error, but it is not the same with my case. What is wrong with my script:
"Insert Into Booklets (id, exam, number_of_booklets, who_gave, when_gave, return_date) values(booklet_seq.NEXTVAL, '" + exam + "', '" + bookletNumbers + "', '" + whoGaveId + "', '" + "to_date(" + gaveTime + ", 'DD/MM/YYYY'))"
As Abra mentioned, you are ending up with
values ( ...., to_date(20/01/2020,'DD/MM/YYYY'), ... )
when you need to have
values ( ...., to_date('20/01/2020','DD/MM/YYYY'), ... )
but please, please, please do not proceed with the formatting of a SQL statement in this way if this is going to be building a true application for your workplace.
Building SQL statements by concatenation is probably the number 1 way people get hacked.
Here's a video I did on this, showing that there are tools out there that can hack your application in just a few minutes the moment you head down this path
https://youtu.be/GRh800IvllY
Binding makes your SQL immune to such hacks, eg
string sql = "select department_name from departments where department_id = " +
":department_id";
OracleCommand cmd = new OracleCommand(sql, conn);
cmd.CommandType = CommandType.Text;
OracleParameter p_department_id = new OracleParameter();
p_department_id.OracleDbType = OracleDbType.Decimal;
p_department_id.Value = 20;
cmd.Parameters.Add(p_department_id);
I would like to select a record from a table based on the field “labcode” specified by the user on a form. There could be multiple records associated with each “labcode” and I would like to select a record that has the highest sum of 10 corresponding fields in the “tblDSA". Fields are named as follows: “A1_MFI”, “A2_MFI”, “C1_MFI”, "C2_MFI", "DR1_MFI", "DR2_MFI"…)
All 10 fields are in 'text' format and sometimes contains a number, text or are left blank. I would only like to sum up records that contain a number in that field. Do I need to create a new field in “tblDSA” that holds the total score or should I avoid storing calculating values in the table?
Dim SQL As String
Dim db As DAO.Database
Dim tblDSA As DAO.Recordset
Set db = CurrentDb
Set tblDSA = db.OpenRecordset("tblDSA")
SQL = "SELECT * Nz((Val[A1_MFI])) + Nz((Val[A2_MFI])) + Nz((Val[B1_MFI])) + Nz((Val[B2_MFI])) + Nz((Val[C1_MFI])) + Nz((Val[C2_MFI])) + Nz((Val[DR1_MFI]))+ Nz((Val[DR2_MFI])) + Nz((Val[DQB1_MFI] + Nz((Val[DQB2_MFI]))as TotalScore FROM tblDSA WHERE [LABCODE] = " & Me.tbLabcode.Value & " ORDER BY TotalScore DESC "
Debug.Print SQL
Set rs = db.OpenRecordset(SQL)
The SQL above contains a syntax error (missing operator), therefore, I can't test it. I'm not sure what is missing?
Nz() is for skipping blank records and Val() is to convert each text field into value. Please let me know if this is a correct approach or I need to do something else? Thanks
Okay, after much back and forth, here is the final result that works for this particular problem:
SELECT TOP 1 *, (Nz(Val(IIf([A1_MFI] Is Null, 0, [A1_MFI]))) + Nz(Val(IIf([A2_MFI] Is Null, 0, [A2_MFI]))) + ...) AS TotalScore
FROM tblDSA
WHERE [LABCODE] = 57
ORDER BY (Nz(Val(IIf([A1_MFI] Is Null, 0, [A1_MFI]))) + Nz(Val(IIf([A2_MFI] Is Null, 0, [A2_MFI]))) + ...) DESC
I thought Access allowed field aliases in the ORDER BY, but it doesn't seem to do that any more, if it did at all.
It looks like you two things
you didn't have a comman after "SELECT *"
missing two brackets in one of your NZ statements
#PhillipXT pointed out the first - and by using his second suggestion, I think the SQL compiler would have pinpointed the missing brackets for you.
Try this with a copy / paste
SQL = "SELECT *, Nz((Val[A1_MFI])) + Nz((Val[A2_MFI])) + Nz((Val[B1_MFI])) + _
Nz((Val[B2_MFI])) + Nz((Val[C1_MFI])) + Nz((Val[C2_MFI])) + Nz((Val[DR1_MFI])) + _
Nz((Val[DR2_MFI])) + Nz((Val[DQB1_MFI])) + Nz((Val[DQB2_MFI])) AS TotalScore _
FROM tblDSA _
WHERE [LABCODE] = " & Me.tbLabcode.Value & _
" ORDER BY TotalScore DESC "
I met a strange problem. I wanted to add string and string but it did not add together in actual.
Below is my code:
sql = "insert into Table (a,b,c,d) values ('" + a.value + "',b,'" + c.value + "',0)"
I use MessageBox to show this string and it just shows
insert into Table (a,b,c,d) values ('a
How can I modify it?
Always use an ampersand "&" when appending strings in VB.NET.
Change the code to
sql = "insert into Table (a,b,c,d) values ('" & a.value & "',b,'" & c.value & "',0)"
you ca use + as below
sql = "insert into Table (a,b,c,d) values ('" + a.value.ToString() + "',b,'" + c.value.ToString() + "',0)"
you need to convert the values to string if they are already not strings
but here you specify ,b, without '', if it is string then you need to add that as below
sql = "insert into Table (a,b,c,d) values ('" + a.value.ToString() + "','b','" + c.value.ToString() + "',0)"
if you using & operator then you don't need to convert to strings. read more about this check this link.
all above for string Concatenation but regarding SQL statement I would recommend you to use parameterized SQL statement.
How do I create a parameterized SQL query? Why Should I?
Haven't come across this in ages and when I searched for the solution I couldn't find one. I think its called overloading in SQL. Basically when I have "" (an empty string) for any parameter in this SQL I don't want to set a value in the database...
NOTE: I want to do it at a SQL level not do it at a C# level because its sloppy that way.
string Sql = "IF NOT EXISTS (SELECT * FROM tbl_FileSystemReferences) "
+ "INSERT INTO tbl_FileSystemReferences (UploadDir) VALUES (null) "
+ "UPDATE tbl_FileSystemReferences SET "
+ "UploadDir=#UploadDir, "
+ "ThumbnailDir=#ThumbnailDir, "
+ "ArchiveDir=#ArchiveDir, "
+ "RealDir=#RealDir, "
+ "FlashDir=#FlashDir, "
+ "AssociatedFilesDir=#AssociatedFilesDir, "
+ "EnableArchiving=#EnableArchiving, "
+ "AppWideDir=#AppWideDir, "
+ "FFmpegDir=#FFmpegDir, "
+ "InstallationDir=#InstallationDir ";
SqlCommand Command = new SqlCommand(Sql);
Command.Parameters.AddWithValue("#UploadDir", f.UploadDir);
Command.Parameters.AddWithValue("#ThumbnailDir", f.ThumbnailDir);
Command.Parameters.AddWithValue("#ArchiveDir", f.ArchiveDir);
Command.Parameters.AddWithValue("#RealDir", f.RealDir);
Command.Parameters.AddWithValue("#FlashDir", f.FlashDir);
Command.Parameters.AddWithValue("#AssociatedFilesDir", f.AssociatedFilesDir);
Command.Parameters.AddWithValue("#EnableArchiving", f.EnableArchiving);
Command.Parameters.AddWithValue("#AppWideDir", f.AppWideDir);
Command.Parameters.AddWithValue("#FFmpegDir", f.FFmpegDir);
Command.Parameters.AddWithValue("#InstallationDir", f.InstallationDir);
ExecuteNonQuery(Command);
I know there is a way I used to do this with stored procedure I just cant remember how (I think it's called overloading)....
Cheers,
Can you create a stored procedure rather than passing the command as text?
That way you can break each of the lines like "UploadDir=#UploadDir," into its own variable and only add it to the command if it is not null or not empty string
one way would be on a stored procedure, where you would receive all those parameters, then before the query either:
you allow to pass null
you convert each parameter to null if they are empty as:
select #UploadDir = null where #UploadDir = ''
you would do that for all your parameters, then on update query:
IF NOT EXISTS (SELECT * FROM tbl_FileSystemReferences)
INSERT INTO tbl_FileSystemReferences (UploadDir) VALUES (null)
UPDATE tbl_FileSystemReferences SET
UploadDir=coalesce(#UploadDir, UploadDir),
ThumbnailDir=coalesce(#ThumbnailDir, ThumbnailDir),
ArchiveDir=coalesce(#ArchiveDir, ArchiveDir),
RealDir=coalesce(#RealDir, RealDir),
FlashDir=coalesce(#FlashDir, FlashDir),
AssociatedFilesDir=coalesce(#AssociatedFilesDir, AssociatedFilesDir),
EnableArchiving=coalesce(#EnableArchiving, EnableArchiving),
AppWideDir=coalesce(#AppWideDir, AppWideDir),
FFmpegDir=coalesce(#FFmpegDir, FFmpegDir),
InstallationDir=coalesce(#InstallationDir, InstallationDir)
I have the following table in a SQLite3 database:
CREATE TABLE overlap_results (
neighbors_of_annotation varchar(20),
other_annotation varchar(20),
set1_size INTEGER,
set2_size INTEGER,
jaccard REAL,
p_value REAL,
bh_corrected_p_value REAL,
PRIMARY KEY (neighbors_of_annotation, other_annotation)
);
I would like to perform the following query:
SELECT * FROM overlap_results WHERE
(neighbors_of_annotation, other_annotation)
IN (('16070', '8150'), ('16070', '44697'));
That is, I have a couple of tuples of annotation IDs, and I'd like to fetch
records for each of those tuples. The sqlite3 prompt gives me the following
error:
SQL error: near ",": syntax error
How do I properly express this as a SQL statement?
EDIT I realize I did not explain well what I am really after. Let me try another crack at this.
If a person gives me an arbitrary list of terms in neighbors_of_annotation that they're interested in, I can write a SQL statement like the following:
SELECT * FROM overlap_results WHERE
neighbors_of_annotation
IN (TERM_1, TERM_2, ..., TERM_N);
But now suppose that person wants to give me pairs of terms if the form (TERM_1,1, TERM_1,2), (TERM_2,1, TERM_2,2), ..., (TERM_N,1, TERM_N,2), where TERM_i,1 is in neighbors_of_annotation and TERM_i,2 is in other_annotation. Does the SQL language provide an equally elegant way to formulate the query for pairs (tuples) of interest?
The simplest solution seems to be to create a new table, just for these pairs,
and then join that table with the table to be queried, and select only the
rows where the first terms and the second terms match. Creating tons of AND /
OR statements looks scary and error prone.
I've never seen SQL like that. If it exists, I would suspect it's a non-standard extension. Try:
SELECT * FROM overlap_results
WHERE neighbors_of_annotation = '16070'
AND other_annotation = '8150'
UNION ALL SELECT * FROM overlap_results
WHERE neighbors_of_annotation = '16070'
AND other_annotation = '44697';
In other words, build the dynamic query from your tuples but as a series of unions instead, or as a series of ANDs within ORs:
SELECT * FROM overlap_results
WHERE (neighbors_of_annotation = '16070' AND other_annotation = '8150')
OR (neighbors_of_annotation = '16070' AND other_annotation = '44697');
So, instead of code (pseudo-code, tested only in my head so debugging is your responsibility) such as:
query = "SELECT * FROM overlap_results"
query += " WHERE (neighbors_of_annotation, other_annotation) IN ("
sep = ""
for element in list:
query += sep + "('" + element.noa + "','" + element.oa + "')"
sep = ","
query += ");"
you would instead have something like:
query = "SELECT * FROM overlap_results "
sep = "WHERE "
for element in list:
query += sep + "(neighbors_of_annotation = '" + element.noa + "'"
query += " AND other_annotation = '" + element.oa + "')"
sep = "OR "
query += ";"
I'm not aware of any SQL dialects that support tuples inside IN clauses. I think you're stuck with:
SELECT * FROM overlap_results WHERE (neighbors_of_annotation = '16070' and other_annotation = '8150') or (neighbors_of_annotation = '16070' and other_annotation = '44697')
Of course, this particular query can be simplified to something like:
SELECT * FROM overlap_results WHERE neighbors_of_annotation = '16070' and (other_annotation = '8150' or other_annotation = '44697')
Generally SQL WHERE-clause predicates only allow filtering on a single-column.