SQL Server query behaves differently interactively than over JDBC - omits some tables - sql-server

I've been trying to retrieve constraint data for all tables using an SQL query over JDBC.
My test database has only 3 tables.
If I execute the query interactively using MS SQL Server Management Studio, I get all the results that I expect (ie. 3 rows - there's a primary key in each of 3 tables).
if I use the JDBC method to specifically retrieve primary keys (as below) then I also correctly get 3 results:
ResultSet rs = dbmd.getPrimaryKeys(jdbcCatalog, jdbcSchema, jdbcTableName);
If I use the exact same SQL statement (that I used interactively and got 3 results back) as a query over JDBC (using executeQuery() shown below) then I only get 1 result instead of the expected 3.
String query =
"select PK.CONSTRAINT_NAME, PK.TABLE_SCHEMA, PK.TABLE_NAME " +
"from information_schema.TABLE_CONSTRAINTS PK";
ResultSet rs = null;
try {
Statement stmt = con.createStatement();
rs = stmt.executeQuery(query);
}catch (Exception exception) {
// Exception handler code
}
while (rs.next()){
// Only executes once.
}
I would be very grateful if someone could explain why the SQL query over JDBC is performing differently to the exact same SQL query performed interactively. Could it be a security/ownership issue? (although the JDBC call getPrimaryKeys() doesn't suffer this)
Thanks.

I don't see where you're setting your database context, but I suspect that that's the issue. As a test, you can change your statement to "select db_name()" and see what it returns. If it's not the database that you think that you should be in, that's your issue.

Related

How to access information schema using a pypika query?

I'm trying to get the names of the columns from a table in an Azure SQL database using a PyPika SQL query, but keep running into trouble. Here's the code I'm using to generate the query:
def dbView(table):
infoSchema = ppk.Table("INFORMATION_SCHEMA.COLUMNS")
return ppk.MSSQLQuery.from_(infoSchema).select(infoSchema.COLUMN_NAME).where(infoSchema.TABLE_NAME == table)
I created another function that uses the PyODBC library to get the SQL from the query, execute it against the database, and return all the rows:
def getData(query: ppk.Query):
'''
Execute a query against the Azure db and return
every row in the results list.
'''
print("QUERY: ", query.get_sql())
conn = getConnection()
with conn.cursor() as cursor:
cursor.execute(query.get_sql())
return cursor.fetchall()
I know the getData() function works because when I pass it a simple select query, everything works correctly. However, when I try to use the query generated by pypika above, I get the following error:
pyodbc.ProgrammingError: ('42S02', "[42S02] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Invalid object name 'INFORMATION_SCHEMA.COLUMNS'. (208) (SQLExecDirectW)")
To make sure this wasn't just some kind of permissions error, I wrote the following query by hand and executed it using the getData() function and it worked just fine:
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Validation'
I also printed out the query that pypika generated to the console. The only difference appears to be the addition of some double quotes:
SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA.COLUMNS" WHERE "TABLE_NAME"='Validation'
What am I doing wrong? For some reason, this error appears to be limited to specifically the information schema table, because I have used similar queries several other times in my code without issue. I know I can just use the query I wrote by hand, but the point of using PyPika was to make all my SQL queries more readable and reusable - it'd be nice to understand why it doesn't work in this very specific situation.
Thanks!
It apparently has an API to schema-qualify tables.
from pypika import Table, Query, Schema
views = Schema('views')
q = Query.from_(views.customers).select(customers.id, customers.phone)
https://pypika.readthedocs.io/en/latest/2_tutorial.html#tables-columns-schemas-and-databases

Entity Framework query never returns

I have a very simple EF query below that never returns. The call to Any() just hangs.
if (!_context.SalesRoundRobinAssignments.Any()) return salesPeopleIds.First();
When I look at the sql profiler I don't see that query being executed however I do see the following.
SQL: BatchStarting select serverproperty('EngineEdition')
SQL: BatchCompleted select serverproperty('EngineEdition')
I've also tried adding this before the query but nothing gets written to the output window aside from the same serverproperty query shown above.
_context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
Any ideas what else I can look at to figure out what's going on?
Did you check the connection string from your web.config/app.config that your Entity Framework Context uses to connect with the database? The query can be executing in another database and that's why you don't see nothing with the SQL profile.
Try to debug and see in execution time, which connection string your application is passing to string connectionString parameter:
public YourDBContext(string connectionString): base(connectionString)
{
}

Complete Query from SQLCommand with Parameters

Using SQLCOmmand to insert row in database. SQL Command is using parameters.
To get the query while debugging at Immediate window I use
?_cmd.CommandText
Result:
"UPDATE TABLE SET Smth=#Smth, Smth2=#Smth2 "
How to get complete query where I instead of #Smth and #Smth2 will have values read from parameters?
If you have access to SSMS, then you could use SQL Server Profiler to trace the actual SQL commands being issued by your VB.NET application when you run it.
Note that running SQL Server Profiler has a performance overhead on the database server, so would strongly advise against running it on a Production server or a server where you would affect others.
Some links on how to get started with SQL Server Profiler...
https://www.mssqltips.com/sqlservertutorial/272/profiler-and-server-side-traces/
http://blog.sqlauthority.com/2009/08/03/sql-server-introduction-sql-server-2008-profiler-complete/
You can write a helper method:
public static class Helper
{
public static string ToString(this DbParameterCollection params, string query)
{
return params.Cast<DbParameter>().Aggregate(query, (c, p) => c.Replace(p.ParameterName, p.Value.ToString()));
}
}
try :
INSERT INTO TABLE SET Smth=#Smth, Smth2=#Smth2 WHERE <somecondition>
Select #Smth,#Smth2

how can I get pyodbc to perform a "SELECT ... INTO" statement without locking?

I'm trying to copy a table in SQL Server, but a simple statement seems to be locking my database when using pyodbc. Here's the code I'm trying:
dbCxn = db.connect(cxnString)
dbCursor = dbCxn.cursor()
query = """\
SELECT TOP(10) *
INTO production_data_adjusted
FROM production_data
"""
dbCursor.execute(query)
The last statement returns immediately, but both LINQPad and SQL Server Management Studio are locked out of the database afterwards (I try to refresh their table lists). Running sp_who2 shows that LINQPad/SSMS are stuck waiting for my pyodbc process. Other databases on the server seem fine, but all access to this database gets held up. The only way I can get these other applications to resolve their stalls is by closing the pyodbc database connection:
dbCxn.close()
This exact same SELECT ... INTO statement statement works fine and takes only a second from LINQPad and SSMS. The above code works fine and doesn't lock the database if I remove the INTO line. It even returns results if I add fetchone() or fetchall().
Can anyone tell me what I'm doing wrong here?
Call the commit function of either the cursor or connection after SELECT ... INTO is executed, for example:
...
dbCursor.execute(query)
dbCursor.commit()
Alternatively, automatic commit of transactions can be specified when the connection is created using autocommit. Note that autocommit is an argument to the connect function, not a connection string attribute, for example:
...
dbCxn = db.connect(cxnString, autocommit=True)
...

How to write a parameterized SQL query?

I am trying this query to fetch my value from a MS SQL database on basis of two conditions but still I am getting exception in the syntax part.
Can anybody tell me what is the correct way to write a parameterized query in R?
Following is the query I used:
query<- paste0("SELECT [value] FROM [RiskDashboard].[dbo].[tbl_Simulation]
where Row_Id=", row_id[c(1),] ," AND Script_Id=", script_id[c(1),] ,)
T_data<-sqlQuery(ch,query)
print(T_data)
Parameterizing data is very important - especially from a security perspective. The examples you have are string concatenations and are subject to SQL injections.
The RODBCext package does have support for parameterization.
First - standard SQL parameterization syntax:
SELECT ColA, ColB FROM MyTable where FirstName = ? and LastName = ?
Each ? mark indicates in order the values that will appear in a vector. This syntax is true for ODBC regardless of platform. Others have extended to support position. eg. OLEDB supports #P1, #P2 etc.
While maybe not important for your R queries - in a multi-user system parameterized queries execute faster because the query plan is stored by the database-server (true of both Oracle and SQL Server).
To semi-plagiarize from the documentation:
library(RODBCext)
connHandle <- odbcConnect("myDatabase")
data <- sqlExecute(connHandle, "SELECT * FROM myTable WHERE column = ?", 'myValue', fetch = TRUE)
odbcClose(connHandle)
Documentation is here: https://cran.r-project.org/web/packages/RODBCext/vignettes/Parameterized_SQL_queries.html
More discussion here: Parameterized queries with RODBC
i got the correct way as follows:
query<- paste0("SELECT [Row_Id],[Script_id],[value] FROM
[RiskDashboard].[dbo]. [tbl_Simulation] where Row_Id='",row_id[c(i),],"'
AND Script_Id='",script_id[c(i),],"'")

Resources