Sqlite Optional Parameters? - sqlite

I have a log table, using System.Data.Sqlite (C# on .NET 4.5) to write to a single table with 12 columns. Some of the columns might be written for a row, some might not. Is there a way to have a single parameterized Insert statement, only specifying n parameters, and let the rest automatically set to null?
I am thinking of the equivalent of a MS SQL Server stored procedure where multiple input parameters can be specified as null, and then a single insert statement within the sproc would insert nulls as needed.
Thanks.

Use null or DBNull.Value; see
NULL values and SQLiteParameters.

Related

Do you need parameterized SQL searches if you check the inputs?

I'm writing an R Shiny/SQLite app. In the app, I have a function that returns a column from one of the tables in my SQLite database, with the function taking the table name as an input.
Before sending the query to SQLite, the function checks that the table name equals one of the table names that the user is allowed to access. However, I am not using a parameterized query, because the term I'm changing is not a variable used for comparison but the name of the table to extract information from. (There might be a way to make this work anyway with a parameterized search, I suppose.)
My question is whether this is safe from an SQL injection? Can the query be altered on its way from the server to the database, or only from an alteration in the ui input to the server?
(Bear with me, I am new to SQLite.)
Assuming your query is being concatenated as follows:
tbl <- "yourTable"
sql <- paste0("select * from ", tbl, " where some_col = 1")
Then there should be no chance of SQL injection, assuming you check the incoming table name and verify that it matches a table name in your whitelist. Note that this step is critical here to keeping things safe. Let's say that you didn't sterilize the incoming table name. Then, consider this:
tbl <- "yourTable; delete from yourTable"
This would result in the following query being submitted for execution:
select * from yourTable; delete from yourTable where some_col = 1;
Assuming your SQLite driver allows multiple SQL statements to execute, the above hack/trick might end up deleting data from a large portion of one of your tables.
So, your approach should be safe provided that you check the table name. Note that strictly speaking the table name itself is not a parameter in a parameterized query. Rather, only the literal values in the query are parameters.
SQL query parameters cannot be used in place of a table name anyway, so comparing the table name to a list of known authorized tables is your only option.
Yes, it is safe. If you're in control of the set of values that can be interpolated into the SQL query, then you can prevent unauthorized SQL injection.
Note that some other elements of SQL queries cannot be parameters:
Any identifier, e.g. a table name, column name, or schema name.
Expressions
Lists of values in an IN ( ... ) predicate. Use one parameter per value in the list.
SQL keywords.
A query parameter can be used only in place of a single scalar value. That is, where you would use a quoted string literal, quoted date literal, or numeric literal.
The problem of SQL injection is only the user input. Nothing happens to the query on its way from the server to the database (well a malware could in theory alter it, but then even a parametrized query wouldn't help).
I.e., if you create a SQL string like this (C#):
sql = "SELECT * FROM " + tableName;
Then a user might enter a tableName like
MyTable; DROP TABLE MyTable
Guess what happens.
So, if you check the table name, you are on the safe side.

How to use variables in sqlite

Created the following code in SQL however need to use it in sqlite (phonegap specifically).
INSERT INTO actions(Action) VALUES ('Go to the pub');
SET #aid = LAST_INSERT_ID();
INSERT INTO statements(statement, Language) VALUES ('Have a pint', 'English');
SET #sid = LAST_INSERT_ID();
INSERT INTO Relationships(SID,AID) VALUES (#sid,#aid);
The issue we are having however is how to declare the variables in sqlite.
The LAST_INSERT_ID() will become last_insert_rowid(), however what is the sqlite version of SET #aid = ?
SQLite does not have variables.
In an embedded database such as SQLite, there is no separate server machine or even process, so it would not make sense to add a programming language to the DB engine when the same control flow and processing logic could be just as well done in the application itself.
Just use three separate INSERT statements.
(In WebSQL, the result object has the insertId property.)

Oracle SQL Update passed as parameter (into stored procedure) string from .NET

I would like to know how to accomplish this task. I've looked at CASE, DECODE or IF condition and I'm not able to make it work. My goal is to pass a block of predefined column/value pair constructed from ASP.NET data to my Oracle stored procedure. I am trying to only update certain columns out of many to preserve other columns not needing updates. So here's my set up:
Stored procedure:
UpdateSelectedColumns(myValuePairString, updatedBy)
-- Passed variable from ASP.NET, myValuePairString = 'col1 = 10,col2 = 'Dog''
-- update statement final
UPDATE MyTable
SET
col1 = 10,
col2 = 'Dog'
col3 = 'john';
COMMIT;
Thank you in advance...
Ricky
For once I'm gonna advise to not use a stored proc. There is no point here in using a stored procedure.
As it is your stored procedure would blindly accept its arguments and execute the update without adding any value. Furthermore, by using this procedure, you preclude the use of binds and exposes yourself to bugs (whenever you encouner a value with a quote '), performance hit and SQL injection vulnerability.
The advantage of PL/SQL (simple transparent binding, transparent use and reuse of cursors, strict static SQL parsing and metadata dependancy) are all pointless if you take an aribtrary string as argument and put it in a dynamic cursor.
You'll be better off to use your language native cursors and use bind variables.
If you really want to use PL/SQL, replace your single argument with a couple of tables. One for the column names, one for the variable values. You could then use DBMS_SQL to parse the statement and use appropriate bind variables. You'll need some convention to be able to parse date, number and character values. You'll need to read metadata from the database to check the datatypes. This would be a lot of code for not a bit of value.

Updating values and returning updated values in Entity framework

i have a table which i use to implement a sequence in Sql Server 2008. The sequence table has just 1 column which is an integer.
I want to know if i can do something like this
update dbo.MySequence set val=val+1 output inserted.val
and return value without using stored procedures in Entity Framework.
Thanks.
Why to avoid stored procedures? Using stored procedures is part of using EF. You don't have to create stored procedure but you still have to call direct SQL (for example with context.ExecuteStoreQuery). For example on MS SQL you can use:
DECLARE #val INT
UPDATE dbo.MySequence SET #val = val = val + 1
SELECT #val
But it is better to have sequences named (with additional column).

Retrieve the PK using ##identity

I'm building a website using ASP.NET and SQL Server, and I use
SELECT PK FROM Table WHERE PK = ##identity
My question is which is better and more reliable to retrieve the last inserted PK for multiuser website, using ##identity or using this:
SELECT MAX(PK) FROM Table WHERE PK = Session ("UserID")
I'm not sure exactly what you want to achieve, but the recommended way to retrieve the primary key value of the last statement on a connection is to use SCOPE_IDENTITY()
##Identity is particularly risky where you are using triggers, since it returns the last generated identity value, including those generated by triggers flowing on from a statement.
MSDN has the following to say:
SCOPE_IDENTITY and ##IDENTITY return
the last identity values that are
generated in any table in the current
session. However, SCOPE_IDENTITY
returns values inserted only within
the current scope; ##IDENTITY is not
limited to a specific scope.
You should certainly use SCOPE_IDENTITY() in favour of the MAX(PK) approach - any number of possible future changes could invalidate this method.
For SQL Server 2005 and above...
You can do the INSERT and SELECT in one call using the OUTPUT clause...
INSERT MyTable (col1, col2, ..., coln)
OUTPUT INSERTED.keycol, INSERTED.col1, INSERTED.col2, ..., INSERTED.coln
VALUES (val1, val2, ..., valn)
Otherwise, you only use SCOPE_IDENTITY()
As mentioned by #David Hall the ##IDENTITY keyword returns the most recently created identity for your current connection, not always the identity for the recently added record in your query and may return an incorrect value. Using MAX(PK) there is a higher chance for an incorrect value and I'd strongly recommend against using it. To avoid the any race conditions I'd suggest that you use SCOPE_IDENTITY() to return the identity of the recently added record in your INSERT SQL Statement or Stored Procedure.
Depends on what you're trying to accomplish. If you want to return the just-generated ID to the ASP.NET code (a typical scenario), then ##identity is your friend. In a high-concurrency situation, mak(PK) is not even guaranteed to be the PK you're after.

Resources