I have a SQL query
var sql = "Select * From Foo Where Bar = {0}"
I want to execute this using Entity Framework, but I want to impose an extra restriction, to see if column Id is in a certain range:
List<int> ids = ...;
var MyFoos = context.Foos.SqlQuery<Foo>(sql).Where(x => ids.Contains(x.Id));
Is this likely to result in efficient selection from the database, or would it end up executing the whole of "Select * From Foo Where Bar = {0}" first and only then filtering for the IDs?
The SQL statement in sql will be executed database side, and results will be returned to the client.
The filter .Where(x => ids.Contains(x.Id)); will then be executed against the results of your sql query, client side.
The .Where will not be translated to SQL.
I verified this using SQL Profiler on a similar query.
Related
In SQL you can create a dynamic SQL statement when the list of conditions (WHERE) is not known in advance, but is built at code execution. So sometimes I would like a subset of records (like ids matching an array), but in other cases I don't want the condition to be applied (hence return the whole list).
In pure SQL there is this solution:Stackoverflow: SQL WHERE column = everything
SELECT * FROM table WHERE id = id
More here: Stackoverflow: Why would someone use WHERE 1=1 AND in a SQL clause?
How would I do this using the DSL from Active Record?
Both of these will work: (as will many more)
.where(MyModel.arel_attribut(:id).eq(MyModel.arel_attribute(:id)))
# OR
.where(Arel.sql("1=1"))
This "always true" type conditioning was generally used for query assembly in Stored Procedures or in String concatenation where you would always have a WHERE clause but then may not have any conditions e.g.
SET #sqlString = 'SELECT * FROM table WHERE 1=1'
IF (#var IS NOT NULL)
SET #sqlString = #sqlString + ' AND "column" LIKE ''%' + #var + '%'' '
EXEC (#sqlString)
# OR
sqlString = "SELECT * FROM table WHERE 1=1"
if someCondition
sqlString = sqlString + " AND column = " + value
end if
but all of this seems antiquated (especially in regards to Rails).
ActiveRecord avoids all of this by using a library called Arel which assembles the SQL just prior to execution.
ActiveRecord provides a convenience method (#all) to generate a similar concept of select everything. You can just call MyModel.all which will return a chainable ActiveRecord::Relation you can then apply conditions, or not, you can add ORDER BY, GROUP BY, LIMIT, HAVING, etc. statements, it is up to you in code and at runtime.
You can utilize this chainability to "assemble" these conditions as you see fit e.g.
q = MyModel.all
q.where!(name: "engineersmnky") if find_my_name?
These calls do not even have to make "logical" sense in SQL statement order because Arel knows the order in which to assemble these statements in order to form a coherent query. e.g.
MyModel.having("COUNT(column) > 1")
.order(:name)
.group(:name)
.select("name, COUNT(column) AS counter")
.where(x: 12)
.limit(2)
This is completely jumbled from a SQL standpoint but when the actual query is assembled it will be ordered correctly.
Chaining where clauses in Rails is quite easy
dataset = User.all
dataset = dataset.where(name: "John") if filter_name?
dataset = dataset.where("age > ?", 20) if filter_age?
dataset
I want to write a query that examines all the tables in an SQLite database for a piece of information in order to simplify my post-incident diagnostics (performance doesn't matter).
I was hoping to write a query that uses the sqlite_master table to get a list of tables and then query them, all in one query:
SELECT Name
FROM sqlite_master
WHERE Type = 'table' AND (
SELECT count(*)
FROM Name
WHERE conditions
) > 0;
However when attempting to execute this style of query, I receive an error no such table: Name. Is there an alternate syntax that allows this, or is it simply not supported?
SQLite is designed as an embedded database, i.e., to be used together with a 'real' programming language.
To be able to use such dynamic constructs, you must go outside of SQLite itself:
cursor.execute("SELECT name FROM sqlite_master")
rows = cursor.fetchall()
for row in rows:
sql = "SELECT ... FROM {} WHERE ...".format(row[0])
cursor.execute(sql)
I am working ServiceStack.OrmLite using MS SQL Server. I would like to execute raw SQL against database but original documentation contains description of how to do it with SELECT statement only. That is not enough for me.
I cant find the way to run anything as simple as that:
UPDATE table1
SET column1 = 'value1'
WHERE column2 = value2
Using, for example:
var two = db.Update(#"UPDATE table1
SET column1 = 'value1'
WHERE column2 = value2");
Running this expressions with db.Update() or db.Update<> produces uncomprehensive errors like
Incorrect syntax near the keyword 'UPDATE'.
I would like to use raw sql because my real UPDATE expression uses JOIN.
db.Update is for updating a model or partial model as shown in OrmLite's Documentation on Update. You can choose to use the loose-typed API to build your update statement, e.g:
db.Update(table: "table1",
set: "column1 = {0}".Params("value1"),
where: "column2 = {0}".Params("value2"));
The Params extension method escapes your values for you.
Otherwise the way to execute any arbitrary raw sql is to use db.ExecuteSql().
If it is a SELECT statement and you want to execute using raw sql you can use:
List<Person> results = db.SqlList<Person>("SELECT * FROM Person WHERE Age < #age", new { age=50});
Reference: https://github.com/ServiceStack/ServiceStack.OrmLite#typed-sqlexpressions-with-custom-sql-apis
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
rs.last() gives Invalid operation for forward only resultset : last
So I'm trying to understand the result set cursor and I'm having an issue with where the cursor is apparently.
I have a very small application that assigns a new integer id automatically, which will be the last entry into the database, therefore the highest integer. I'm trying to get to the last entry like this (rs is result set) so I can use its value:
rs.last
and then assigning the_new_id to rs.getInt(1)...
However, I get the "Invalid operation for forward only resultset : last" sql exception.
Right now I have a big "kludge" to make this work:
while(rs.next())
your_new_id = rs.getInt(1);
and then I just assign the new id that way. :-\
How can I implement this same behavior more elegantly using last?
Any help is appreciated.
By default, result sets are forward-only, meaning that the only thing you can do to change the position of the cursor is next() (which is all you need if you order by ID in descending order).
The javadoc explains it:
A default ResultSet object is not updatable and has a cursor that
moves forward only. Thus, you can iterate through it only once and
only from the first row to the last row. It is possible to produce
ResultSet objects that are scrollable and/or updatable. The following
code fragment, in which con is a valid Connection object, illustrates
how to make a result set that is scrollable and insensitive to updates
by others, and that is updatable. See ResultSet fields for other
options.
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
Apparently you are trying to retrieve the ID that was generated by a previous INSERT statement. You should not use a separate SELECT statement for that (which is not transaction safe and does impose an unnecessary load on the database).
To retrieve a generated ID, use the following JDBC calls:
String insert = "insert into some_table (... ";
PreparedStatement pstmt = con.prepareStatement(insert, new String[] {"ID"});
int rowsInserted = pstmt.executeUpdate();
ResultSet idResult = pstmt.getGeneratedKeys();
int newId = -1;
if (rs.next()) {
newId = rs.getINt(1);
}
This will retrieve the value that was generated for the ID column during the INSERT. This will be faster than doing a SELECT to get the latest ID, but more importantly it is transaction safe.
While going through some SQL books I found that examples tend to use question marks (?) in their queries. What does it represent?
What you are seeing is a parameterized query. They are frequently used when executing dynamic SQL from a program.
For example, instead of writing this (note: pseudocode):
ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = 7")
result = cmd.Execute()
You write this:
ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = ?")
cmd.Parameters.Add(7)
result = cmd.Execute()
This has many advantages, as is probably obvious. One of the most important: the library functions which parse your parameters are clever, and ensure that strings are escaped properly. For example, if you write this:
string s = getStudentName()
cmd.CommandText = "SELECT * FROM students WHERE (name = '" + s + "')"
cmd.Execute()
What happens when the user enters this?
Robert'); DROP TABLE students; --
(Answer is here)
Write this instead:
s = getStudentName()
cmd.CommandText = "SELECT * FROM students WHERE name = ?"
cmd.Parameters.Add(s)
cmd.Execute()
Then the library will sanitize the input, producing this:
"SELECT * FROM students where name = 'Robert''); DROP TABLE students; --'"
Not all DBMS's use ?. MS SQL uses named parameters, which I consider a huge improvement:
cmd.Text = "SELECT thingA FROM tableA WHERE thingB = #varname"
cmd.Parameters.AddWithValue("#varname", 7)
result = cmd.Execute()
The ? is an unnamed parameter which can be filled in by a program running the query to avoid SQL injection.
The ? is to allow Parameterized Query. These parameterized query is to allow type-specific value when replacing the ? with their respective value.
That's all to it.
There are several reasons why it's good practice to use Parameterized Queries. In essence, it's easier to read and debug, and circumvents SQL injection attacks.
It's a parameter. You can specify it when executing query.
I don't think that has any meaning in SQL. You might be looking at Prepared Statements in JDBC or something. In that case, the question marks are placeholders for parameters to the statement.
It normally represents a parameter to be supplied by client.