t-sql ado recordset / SQL Server - tsql

I want to execute a T-SQL statement with ADO-layer. The sql-statement is like:
DECLARE #var TABLE (id int)
INSERT INTO #var SELECT id FROM tblFoo WHERE name='myName' AND idx=2
SELECT * FROM tblFoo WHERE id IN (SELECT * FROM #var)
In the SQL Server management console all works well. But if I use that for opening a ADO_Recordset via Open(sql) that recordset will not be filled/opened. eof() said: recordset is not opened.
The question ist: How to exectue T-SQL stataments that will result a recordset on the ADO layer?

In the Options parameter of the Open() method you need to pass in CommandTypeEnum.adCmdText.
see this link for more info http://msdn.microsoft.com/en-us/library/ms675544(v=vs.85).aspx
Also change your query to this:
SELECT * FROM tblFoo WHERE name='myName' AND idx=2

You need to treat this SQL as plain test
something like:
cmd.CommandType = adCmdText

Related

dynamic sql query in postgres

I was attempting to use Dynamic SQL to run some queries in postgres.
Example:
EXECUTE format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition)))
I have to query a table, which is of the form result_%s_table wherein, I need to substitute the correct table name (an id) from an another table.
I get the error ERROR: prepared statement "format" does not exist
Link: string substitution with query result postgresql
EXECUTE ... USING only works in PL/PgSQL - ie within functions or DO blocks written in the PL/PgSQL language. It does not work in plain SQL; the EXECUTE in plain SQL is completely different, for executing prepared statements. You cannot use dynamic SQL directly in PostgreSQL's SQL dialect.
Compare:
PL/PgSQL's EXECUTE ... USING; to
SQL's EXECUTE
See the 2nd last par in my prior answer.
In addition to not running except in PL/PgSQL your SQL statement is wrong, it won't do what you expect. If (select id from ids where condition = some_condition) returns say 42, the statement would fail if id is an integer. If it's cast to text you'd get:
EXECUTE format('SELECT * from result_%s_table', quote_ident('42'));
EXECUTE format('SELECT * from result_%s_table', '"42"');
EXECUTE 'SELECT * from result_"42"_table';
That's invalid. You actually want result_42_table or "result_42_table". You'd have to write something more like:
EXECUTE format('SELECT * from %s', quote_ident('result_'||(select id from ids where condition = some_condition)||'_table'))
... if you must use quote_ident.
CREATE OR REPLACE FUNCTION public.exec(
text)
RETURNS SETOF RECORD
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RETURN QUERY EXECUTE $1 ;
END
$BODY$;
usage:
select * from exec('select now()') as t(dt timestamptz)
Try using
RETURN QUERY EXECUTE '<SQL Command>'
This will return data into form of table. You have to use this into stored function of PostgreSQL.
I have already created on full demonstration on custom filter and custom sorting using dynamic query of PostgreSQL.
Please visit this url:
http://www.dbrnd.com/2015/05/postgresql-dynamic-sql/
These all look more complicated than the OP's question. A different formatting should do the trick.. but it could absolutely the case that I don't understand.
From how I read OP's question, I think others in a similar situation may benefit from how I got it.
I am using Postgre on Redshift, and I ran into this issue and found a solution.
I was trying to create a dynamic query, putting in my own date.
date = dt.date(2018, 10, 30)
query = ''' select * from table where date >= ''' + str(my_date) + ''' order by date '''
But, the query entirely ignores the condition when typing it this way.
However, if you use the percent sign (%), you can insert the date correctly.
One correct way to write the above statement is:
query = ''' select * from table where date >= ''' + ''' '%s' ''' % my_date + ''' order by date '''
So, maybe this is helpful, or maybe it is not. I hope it helps at least one person in my situation!
Best wishes.
EXECUTE will work only on pl/pqsql environment.
instead of EXECUTE try with SELECT
SELECT format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition))
output would be the dynamic query.

sybase cursors in a trigger

I am trying to use a cursor in a trigger on a sybase ASE 15.0.3 system running on Solaris. The purpose for this is that I want to know which column of a table is getting updated. This information I then save in an admin table for further lookups.
create trigger test_trigger on my_table for update as
set nocount on
/* declare cursor */
declare #colname varchar(64)
declare column_name cursor for
select syscolumns.name from syscolumns join sysobjects on (sysobjects.id = syscolumns.id) where sysobjects.name = 'my_table'
/* open the cursor */
open column_name
/* fetch the first row */
fetch column_name into #colname
/* now loop, processing all the rows
** ##sqlstatus = 0 means successful fetch
** ##sqlstatus = 1 means error on previous fetch
** ##sqlstatus = 2 means end of result set reached
*/
while (##sqlstatus != 2)
begin
/* check for errors */
if (##sqlstatus = 1)
begin
print "Error in column_names cursor"
return
end
/* now do the insert if colum was updaed */
if update(#colname)
begin
insert into my_save_table (login,tablename,field,action,pstamp)
select suser_name(),'my_table',#colname,'U',getdate() from inserted
end
/* fetch the next row */
fetch column_name into #colname
end
/* close the cursor and return */
close column_name
go
Unfortunately when trying to run this in isql I get the following error:
Msg 102, Level 15, State 1:
Server 'my_sybase_server', Procedure 'test_trigger', Line 34:
Incorrect syntax near '#colname'.
I did some investigations and found out that line 34 means the following statement:
if update(#colname)
then I tried to just check on 1 column and replaced it by
if update(some_column_name)
That actually worked fine and I don't have any other idea how to fix that. It looks like the update() function somehow not allows to contain a variable. I did not find any additional information on the sybase books or anywhere else in google ect. Does anybody may find a solution for this? Is it may a bug? Are there workarounds for the cursor?
Thanks for any advice
The problem is that update(#colname) is something like update('colname') and needs to be update(colname). In order to you achieve that, you need to use Dynamic SQL.
I've already saw the documentation and it's possible to use:
Dynamically executing Transact-SQL
When used with the string or char_variable options, execute concatenates the supplied strings and variables to execute the
resulting Transact-SQL command. This form of the execute command may
be used in SQL batches, procedures, and triggers.
Check this article for an example on how to use dynamic sql!
If it is not a problem to recreate the trigger every time the table is altered (columns added/dropped) you may just generate the body for your trigger with such query
select
'if update('+c.name+')
set #colname = '''+c.name+'''
'
from syscolumns c where id = object_id('my_table')

Updating generator value issue

I'm currently working on modifying a Firebird v. 1.5 database.
The database structure will be modified running queries from a delphi application using interbase components, the problem I'm facing is that I need to run a lot of queries, some of which include creating generators and updating the generator value, the problem is that I need to achieve this in as few queries as possible, but it seems(at least to me) that this is not really possible, what I'm trying to do is the following:
/* this command creates a generator to be used for table TABLENAME */
CREATE GENERATOR GEN_TABLENAME;
So I've created a generator, now I need to set it's value at the current max id from table TABLENAME, like so:
/* one would expect that the following command would work, well it doesn't */
SET GENERATOR GEN_TABLENAME TO (SELECT MAX(ID) FROM TABLENAME);
Now, is there any workaround for this, or am I forced to:
create the generator
get the max id
update the generator value
and repeat process for every table?
I also expected that
SELECT
SELECT MAX(ID) AS ID_TABLENAME_1 FROM TABLENAME_1,
...
SELECT MAX(ID) AS ID_TABLENAME_N FROM TABLENAME_N
would be a workaround to get the max id's from every table in one command, but it doesn't.
Statement
SET GENERATOR GEN_TABLENAME TO (SELECT MAX(ID) FROM TABLENAME);
mixes DDL (SET GENERATOR) and DML (SELECT), AFAIK this is not generally supported and Firebird doesn't support it for sure.
If you can upgrade to the latest version of Firebird then you could use EXECUTE BLOCK and / or EXECUTE STATEMENT to do it all "in one statement" and server side, but with Firebird 1.5 you have to settle for the long way (one statement to get the current max, then another one update the generator).
With the following trick you can set the generator value to the maximum ID value of a table with one SQL statement in Firebird:
SELECT GEN_ID( GEN_TABLENAME,
(SELECT MAX(ID) FROM TABLENAME) - GEN_ID(GEN_TABLENAME, 0)) FROM RDB$DATABASE;
That works, because GEN_ID( <GeneratorName>, <increment>) gets the generator value and increments it by <increment>. This should work in Firebird 1.5 as well as in newer versions.
You could create a stored procedure and call it from Delphi:
create procedure update_generators
as
declare variable max_id integer;
declare variable table_name char(31);
declare variable generator_name char(31);
begin
/* assuming generator naming convention GEN_XXX -> table name XXX */
for select
trim(g.rdb$generator_name),
substring(trim(g.rdb$generator_name) from 5)
from rdb$generators g
where (coalesce(g.rdb$system_flag, 0) = 0)
into
:generator_name,
:table_name
do
begin
/* assuming that the field name is always ID */
execute statement 'select max(id) from ' || :table_name into :max_id;
execute statement 'set generator ' || :generator_name || ' to ' || :max_id;
end
end^
It looks like execute statement is supported by Firebird 1.5 already.
In Firebird 2.0 and later, you could also wrap the code in a execute block and avoid creating a stored procedure.

Declare a variable in DB2 SQL

Does anyone know how to run the following SQL Server code in DB2?
I am converting SQL Server scripts so that they will run on a DB2 system and am having some problems wrapping my head around the use of variables in DB2.
T-SQL code
This is obviously not the actual code but works well as an example.
DECLARE #INPUT_VALUE INT
SET INPUT_VALUE = 4756
SELECT *
FROM TABLE1
WHERE TABLE1.COLUMN1 = #INPUT_VALUE
I imagine this forum posting, which I quote fully below, should answer the question.
Inside a procedure, function, or trigger definition, or in a dynamic SQL statement (embedded in a host program):
BEGIN ATOMIC
DECLARE example VARCHAR(15) ;
SET example = 'welcome' ;
SELECT *
FROM tablename
WHERE column1 = example ;
END
or (in any environment):
WITH t(example) AS (VALUES('welcome'))
SELECT *
FROM tablename, t
WHERE column1 = example
or (although this is probably not what you want, since the variable needs to be created just once, but can be used thereafter by everybody although its content will be private on a per-user basis):
CREATE VARIABLE example VARCHAR(15) ;
SET example = 'welcome' ;
SELECT *
FROM tablename
WHERE column1 = example ;
I'm coming from a SQL Server background also and spent the past 2 weeks figuring out how to run scripts like this in IBM Data Studio. Hope it helps.
CREATE VARIABLE v_lookupid INTEGER DEFAULT (4815162342); --where 4815162342 is your variable data
SELECT * FROM DB1.PERSON WHERE PERSON_ID = v_lookupid;
SELECT * FROM DB1.PERSON_DATA WHERE PERSON_ID = v_lookupid;
SELECT * FROM DB1.PERSON_HIST WHERE PERSON_ID = v_lookupid;
DROP VARIABLE v_lookupid;

DB2 compound statement using ADO.NET

I want to execute multiple statements from my data access layer using C# dan IBM's DB2 data provider.
(environment: DB2/AS400 os version: V5R4)
eg in TSQL:
declare varA integer;
select varA= count(*) from tableA;
select * from tableB where col1 <= varA
with SQL server ; I can concatenate those 3 statements into a string
and assign the text to DBCommand.CommandText.
How to execute multiple statements(compound statement) against DB2 database via DBCommand (using IBM DB2 data provider)
I tried using begin and end block but still failed
BEGIN
statement1;
statement2;
statement3;
END
Thank you
I do not think it's possible.
I had already tried something similar some time ago, and the only solution I found is to dynamically create a stored procedure, calling it, and finally delete it.