In my test project I register a connection using ":memory" connection string and SqliteDialect.Provider as provider. When trying to run tests that execute arbitrary sql (I have a complex join statement so I cannot use a typed query) I get an error that the table do not exist. In my query I print "SELECT * FROM xxx.Table1" but when looking at the code generated from a typed query I can see that it is "SELECT * FROM xxx_Table1". I need to use schemas for the production code, so is there a way to force ORMLite for Sqlite to generate schemas and not just name prefixes when using the attribute [Schema("xxx")] on my domain models?
SQLite doesn't have schemas so they're simulated by prefixing the schema name before the table name. However this should be a transparent implementation detail for SQLite :memory: DBs as the same table name will be used when creating or querying the table.
If you're creating Custom SQL you should use the tableName returned from:
var modelDef = typeof(Table1).GetModelMetadata();
var tableName = db.GetDialectProvider().GetTableName(modelDef);
var sql = $"SELECT * FROM {tableName}";
Related
In ?DBI::dbListTables we can read :
This should include views and temporary objects
And indeed it does.
How can I see only tables though, excluding views ?
I'm using the driver RPostgres::Postgres() if it matters.
I suggest to the system catalog view pg_tables for tables:
dbGetQuery(con, "SELECT * FROM pg_tables")
The manual:
The view pg_tables provides access to useful information about each table in the database.
Does not contain views, materialized views or temporary tables, only regular tables (including UNLOGGED tables). See:
How to check if a table exists in a given schema
You may want to exclude system tables and only retrieve schema and table name:
dbGetQuery(con, "SELECT schemaname, tablename FROM pg_catalog.pg_tables WHERE schemaname !~ '^pg_' AND schemaname <> 'information_schema'")
I added explicit schema-qualification for the catalog table: pg_catalog.pg_tables. Typically not necessary, but to defend against a messed up search_path setting. See:
How does the search_path influence identifier resolution and the "current schema"
pg_views for views - if you need that:
dbGetQuery(con, "SELECT * FROM pg_views")
The view pg_views provides access to useful information about each view in the database.
I cannot find a way to get the auto-generated keys after an INSERT statement when using the R database interface to PostgreSQL (RPostgreSQL).
Is there a way to do this like in JDBC?
https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#getGeneratedKeys%28%29
Eventually, I have exploited a PostgreSQL-specific SQL extension, the RETURNING clause of an INSERT statement, which returns the generated primary key(s) after executing an INSERT statement. It was also necessary to trick DBI to handle the INSERT query as if it were a SELECT query to get access to the returned values, i.e. the generated keys.
Assume we have the following table in a database: USERS(id, name), where the id is the auto-generated primary key. The following example R code snippet illustrates the concept of getting the generated key from the database, and assigning it to the R object:
query <- sprintf(
"INSERT INTO users (name) VALUES ('%s') RETURNING id",
users$name
)
dbres = dbGetQuery(conn, query)
users$id = dbres$id
With the release of dplyr 0.7.0, it is now supposedly easy to connect to Oracle using the odbc package. However, I am running into a problem accessing tables not inside the default schema (for me it is my username). For example, suppose there is the table TEST_TABLE in schema TEST_SCHEMA. Then, example SQL syntax to get data would be: select * from TEST_SCHEMA.TEST_TABLE'.
To do the same in `dplyr, I am trying the following:
# make database connection using odbc: [here's a guide][1]
oracle_con <- DBI::dbConnect(odbc::odbc(), "DB")
# attempt to get table data
tbl(oracle_con, 'TEST_SCHEMA.TEST_TABLE')
Now, this leads to an error message:
Error: <SQL> 'SELECT *
FROM ("TEST_SCHEMA.TEST_TABLE") "zzz12"
WHERE (0 = 1)'
nanodbc/nanodbc.cpp:1587: 42S02: [Oracle][ODBC][Ora]ORA-00942: table or view does not exist
I think the problem here is the double quotation marks, as:
DBI::dbGetQuery(oracle_con, "select * from (TEST_SCHEMA.TEST_TABLE) where rownum < 100;")
works fine.
I struggled with this for a while until I found the solution at the bottom of the introduction to dbplyr. The correct syntax to specify the schema and table combo is:
tbl(oracle_con, in_schema('TEST_SCHEMA', 'TEST_TABLE'))
As an aside, I think the issue with quotation marks is lodged here: https://github.com/tidyverse/dplyr/issues/3080
There are also the following alternate work-arounds that may be suitable depending on what you wish to do. Since the connection used DBI, one can alter the schema via:
DBI::dbSendQuery(oracle_con, "alter session set current_schema = TEST_SCHEMA")
after which tbl(oracle_con, 'TEST_TABLE') will work.
Or, if you have create view privileges, you can create a "shortcut" in your default schema to any table you are interested in:
DBI::dbSendQuery(oracle_con, "CREATE VIEW TEST_TABLE AS SELECT *
FROM TEST_SCHEMA.TEST_TABLE")
Note that the latter may be more suitable for applications where you wish to copy local data to the database for a join, but do not have write access to the table's original schema.
Let's say i have a table named User.
When I use the Entity Framework to get the records i do like this:
var db = new Context();
var users = db.Users;
It return all the users in my table. OK. If i do this:
var fooUsers = db.Users.Where(u => u.Name == 'foo');
It will give me all the users with name 'foo'. OK. My question is:
The entity framework make a query like:
select * from user where name = 'foo'
Or it load all the users and filter them on the server with lambda expression?
The Sql submitted to your database will contain your where clause. You can use SQL Server Profiler to watch as queries are submitted to your DB.
Entity Framework will translate such a query into a "Store Expression." That is, it will generate a database query -- assuming your data storage is a database -- that will be somewhat similar to the query you included in your question. It very well may name the columns, however, and there are likely to be some other differences.
From here http://msdn.microsoft.com/en-us/library/cc853327.aspx
When you create an ObjectQuery or LINQ query, the query may not be executed immediately. Query execution is deferred until the results are needed, such as during a foreach (C#) or For Each (Visual Basic) enumeration or when it is assigned to fill a List collection. Query execution begins immediately when you call the Execute method on an ObjectQuery or when you call a LINQ method that returns a singleton query, such as First or Any. For more information, see Object Queries and Query Execution (LINQ to Entities).
So when your query has a WHERE clause it will just load the results filtered by the database with the where.
We are trying to build an web application that allows users to select appropriate columns for given database table.
I wonder if there is any API for these - I've googled it a while in vain. Otherwise, if you can give some clues (patterns or sample codes) how to build such a component, that will be great and appreciated.
You could base your application on INFORMATION_SCHEMA views/table. This is documentation for SQL Server, but you can easily find it for other databases too:
http://msdn.microsoft.com/en-us/library/ms186778.aspx
Sample SQLs:
select * from INFORMATION_SCHEMA.TABLES
select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users'
if you want to use this solution with many databases, to separate your application from db engine, you can create about defining IMetadataProvider interface and create implementations for different databases:
interface IMetadataProvider {
...GetTables();
...GetTableColumns();
...GetTableRelations();
//Other functions required by your project
}
You can also create your own query builder interface:
interface IQueryBuilder {
...From(string tableName);
...Top(int numberOfRows); //TOP for SQL SERVER, LIMIT for MySQL
}