How to check a number of inserted/modified records in TADOCommand? - sql

I am using SQL Server database and after calling a simple SQL script I would like to know how many records were affected by last (or only) executed statement in a script.
I cannot find the reference how to achieve this in Delphi's TADOCommand and I know SQL Server gives this information to provider. I am aware of workarounds like getting ##ROWCOUNT in another query, yet this gives some overhead and unnecessary complexity.
Thanks.

Do you use the
function Execute(var RecordsAffected: Integer; const Parameters: OleVariant): _Recordset;
version of the Execute method?
From the doc:
RecordsAffected indicates the number
of records, if the command operates on
data, that are affected by the command
after execution.
So that should give you what you need.
Disclaimer: I cannot test this against SQL Server (don't have it).

Related

next:jdbc How to allow multiple statements for SQL Server

I want to run multiple statements on a single execution against SQL Server. I do it with Node.js but I cannot run the same query using next.jdbc
For example, if I run this:
(def db {:jdbcUrl "jdbc:jtds:sqlserver://localhost:1433/TESTDB;user=sa;password=passwd"})
(def ds (jdbc/get-datasource db))
(jdbc/execute! ds ["select * from EMPLOYEE;select FIRST_NAME from EMPLOYEE;"])
I have also tried to wrap the statement within a transaction with the same result
(jdbc/execute! ds ["BEGIN TRANSACTION select * from EMPLOYEE;select FIRST_NAME from EMPLOYEE; COMMIT"])
I always get the first query.
I have tried Microsoft's JDBC driver also.
Sean Corfield says that if the database supports it, then next.jdbc should support it. next-jdbc: execute multiple statements?
But I cannot make it work
Solution
As indicated by Sean Corfield
(jdbc/execute! ds ["BEGIN select * from EMPLOYEE;select FIRST_NAME from EMPLOYEE; END"] {:multi-rs true})
Yes, you can run multiple statements and multiple result sets back but you have to tell next.jdbc that's the behavior you want.
Take a look at the tests for MS SQL Server running multiple statements: https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc_test.clj#L560-L572
This is mentioned (briefly) in the Getting Started guide: "If you pass the :multi-rs true option to execute!, you will get back a vector of results sets, instead of just one result set: a vector of zero or more vectors."
As far as I know, SQL Server's JDBC driver does not support multiple statements. But, even if it did, you should probably not be using it, as it opens a potential security hole for injection type attacks. Instead, if you really need to execute multiple SQL statements, either refactor your current SQL into a single statement, or else use multiple statements wrapped in a single transaction.
For reference, some other JDBC drivers, such as MySQL, might support multiple statements.

Oracle Sql - Time based sql injection

When trying to do an SQL injection on an Oracle SQL database I have the problem that most of the examples in the tutorials do not work. I already found out that I only can use CASE WHEN a THEN b ELSE c END instead of normal if statements.
The question I have now is how do I get time delay into the injection? Benchmark() and sleep() do not work either.
I already now that the table is named "flag" and the field name I want to read out is named "password".
My only information i get from the database is the time it needed to execute my input (or query since I bypass the input to inject SQL)
I found the following SQL statement on the web at SQL Injection Tutorial
select dbms_pipe.receive_message(('a'),10) from dual;
I am not certain I should be participating in this sort of thing, but since I found it with my first Google Search, I will go ahead and post it.
I tested it and it delayed the result by 10 seconds.

SQL Parameters - where does expansion happens

I'm getting a little confused about using parameters with SQL queries, and seeing some things that I can't immediately explain, so I'm just after some background info at this point.
First, is there a standard format for parameter names in queries, or is this database/middleware dependent ? I've seen both this:-
DELETE * FROM #tablename
and...
DELETE * FROM :tablename
Second - where (typically) does the parameter replacement happen? Are parameters replaced/expanded before the query is sent to the database, or does the database receive params and query separately, and perform the expansion itself?
Just as background, I'm using the DevArt UniDAC toolkit from a C++Builder app to connect via ODBC to an Excel spreadsheet. I know this is almost pessimal in a few ways... (I'm trying to understand why a particular command works only when it doesn't use parameters)
With such data access libraries, like UniDAC or FireDAC, you can use macros. They allow you to use special markers (called macro) in the places of a SQL command, where parameter are disallowed. I dont know UniDAC API, but will provide a sample for FireDAC:
ADQuery1.SQL.Text := 'DELETE * FROM &tablename';
ADQuery1.MacroByName('tablename').AsRaw := 'MyTab';
ADQuery1.ExecSQL;
Second - where (typically) does the parameter replacement happen?
It doesn't. That's the whole point. Data elements in your query stay data items. Code elements stay code elements. The two never intersect, and thus there is never an opportunity for malicious data to be treated as code.
connect via ODBC to an Excel spreadsheet... I'm trying to understand why a particular command works only when it doesn't use parameters
Excel isn't really a database engine, but if it were, you still can't use a parameter for the name a table.
SQL parameters are sent to the database. The database performs the expansion itself. That allows the database to set up a query plan that will work for different values of the parameters.
Microsoft always uses #parname for parameters. Oracle uses :parname. Other databases are different.
No database I know of allows you to specify the table name as a parameter. You have to expand that client side, like:
command.CommandText = string.Format("DELETE FROM {0}", tableName);
P.S. A * is not allowed after a DELETE. After all, you can only delete whole rows, not a set of columns.

How can I programmatically run arbitrary SQL statements against my Hibernate/HSQL database?

I'm looking for a way to programmatically execute arbitrary SQL commands against my DB.
(Hibernate, JPA, HSQL)
Query.createNativeQuery() doesn't work for things like CREATE TABLE.
Doing LOTS of searching, I thought I could use the Hibernate Session.doWork().
By using the deprecated Configuration.buildSesionFactory() seems to show that doWork won't work.
I get "use lacks privilege or object not found" for all the CREATE TABLE statements.
So, what other technique is there for executing arbitratry SQL statements?
There were some notes on using the underlying JDBC Statement, but I haven't figure out how to get a JDBC Connection object from Hibernate to try that.
Note that the hibernate.hbm2ddl.auto=create setting will NOT work for me, as I have ARRAY[] columns which it chokes on.
I don't think there is any problem executing a create table statement with a Hibernate native query. Just make sure to use Query.executeUpdate(), and not Query.list() or Query.uniqueResult().
If it doesn't work, please tell us what happens when you execute it, and join the full stack trace of the exception and the SQL query you're executing.
"use lacks privilege or object not found" in HSQL may mean anything, for example existence of a table with the same name. Error messages in HSQL are completely misleading. Try listing your tables using DatabaseMetadata - you have probably already created the table.

SQL error:8152, but not over max?

I'm part of a team writing an ERP using , Seam, and Jboss, and on one of my pages, I keep getting an SQL error: 8152 whenever I try to input something. SQL error:8152, for those of you who don't know, is when you try to input a value over the maximum limit of the column.
I've double checked my entity and the database, and their maximum value limits are the same (50 nvarchars). In addition, I'm pretty sure that we're not using audit tables. I then put System.out.println(""); all over the place, and found that the error was happening in between these two println(s):
System.out.println("Flushing");
entityManager.flush();
System.out.println("Flushing complete");
Which is part of a method that process all changes to the table. But I'm pretty new to programming and not sure what's going on.
Any help would be appreciated, thanks in advance, Jeff.
P.s. Code on request, but I didn't post it because there is a lot of it all over the place.
I would verify the SQL that is being executed when the flush() is performed. That way you can see the length of your data and verify that it is too big as shown by the DB error.
If you are using Hibernate, you can output SQL to the console. You don't say what your DB is, but if it's SQL Server you can use the profiler to see what SQL is being executed.