MSAccess Insert with sub select wont work - sql

I have simple query, but when I'm trying to execute this query I'm getting error:
Query input must contain at least one table or query. (Error 3067)
Query:
INSERT INTO FV_Ko ( FvId, OldPriceNetto )
SELECT [PFvId], (SELECT FV.PriceNetto1 FROM FV WHERE FV.FVnr = '123');

This should work - it should ask you for [PFvId]
INSERT INTO FV_Ko ( FvId, OldPriceNetto )
SELECT [PFvId], FV.PriceNetto1 FROM FV WHERE FV.FVnr = '123';

If PFvld is a parameter and the query (MyQuery) is saved (part of the MSAccess database), then you should be able to do:
Dim qdf As DAO.QueryDef
Set qdf = db.QueryDefs("MyQuery")
qdf.Parameters("[PFvld]") = myValue
If you compose the query on the fly and execute it, then you might just specify a value when composing the SQL code instead of a parameter (not that it is a better solution though).

The subquery is OK, but you aren't saying where PFvID is coming from. Your INSERT should be something like this:
INSERT INTO FV_Ko ( FvId, OldPriceNetto )
SELECT AnotherTable.PFvId,
(SELECT FV.PriceNetto1 FROM FV WHERE FV.FVnr = '123') FROM AnotherTable

...
SELECT [PFvId], --> you should define a FROM table at end of the query
(SELECT FV.PriceNetto1 FROM FV WHERE FV.FVnr = '123');

Related

I am getting Syntax error in sql (insert)

So, I am trying to add a data if a value in field does not exist. I am keep getting syntax error and not sure where I am getting it wrong.
INSERT INTO COMPANY_TABLE(company_name, company_phone, company_url)
VALUES ('test','010-4843-0000','www.company.com')
WHERE NOT EXISTS (SELECT * FROM COMPANY_TABLE WHERE company_name = 'test');
This is my code.
I am using H2 database
You're trying to combine a values table constructor with syntax of a select query
You can insert into a table using select:
INSERT INTO COMPANY_TABLE(company_name, company_phone, company_url)
SELECT 'test','010-4843-0000','www.company.com'
WHERE NOT EXISTS (SELECT * FROM COMPANY_TABLE WHERE company_name = 'test');

How do I use parameters for the source in a MERGE statement in Informix?

I am trying to execute a merge statement against an Informix database as follows:
MERGE INTO aa_rec AS dest
USING (SELECT '123456' AS id, '111-222-3333' as phone, '' as phone_ext, 'CELL' as aa FROM sysmaster:'informix'.sysdual) AS src
ON dest.id = src.id AND dest.aa = src.aa
WHEN NOT MATCHED THEN
INSERT (dest.id, dest.aa, dest.beg_date, dest.phone, dest.phone_ext, dest.ofc_add_by)
VALUES (src.id, src.aa, TODAY, src.phone, src.phone_ext, 'TEST')
WHEN MATCHED THEN UPDATE SET
dest.phone = src.phone,
dest.phone_ext = src.phone_ext,
dest.beg_date = '10/29/2019',
dest.ofc_add_by = 'TEST'
This statement works as is, with hard-coded values, but I would like to pass parameters for the values in the source table:
USING (SELECT ? AS id, ? as phone, ? as phone_ext, 'CELL' as aa FROM sysmaster:'informix'.sysdual) AS src
When I execute the statement with parameters and valid values, I receive this error:
E42000: (-201) A syntax error has occurred.
Are parameters supported in the source part of the MERGE statement? If they are, where is the error in my syntax?
For context, I'm calling this from ASP.NET using the OleDb provider for Informix.
You have:
SELECT ? AS id, ? as phone, ? as phone_ext, 'CELL' as aa FROM sysmaster:'informix'.sysdual
You can't use placeholders (? symbols) for 'structural' elements of a SELECT statement. You can't provide column names in the placeholders. And passing numbers etc as values via placeholders in the select-list doesn't work either.
I'd probably create a temp table of the appropriate shape, and insert a row into that, and then use the temp table in the select statement:
SELECT '123456' AS id, '111-222-3333' AS phone, '' AS phone_ext, 'CELL' AS aa
FROM sysmaster:'informix'.sysdual
INTO TEMP phone_data;
MERGE INTO aa_rec AS dest
USING (SELECT * FROM phone_data) AS src
ON dest.id = src.id AND dest.aa = src.aa
WHEN NOT MATCHED THEN
INSERT (dest.id, dest.aa, dest.beg_date, dest.phone, dest.phone_ext, dest.ofc_add_by)
VALUES (src.id, src.aa, TODAY, src.phone, src.phone_ext, 'TEST')
WHEN MATCHED THEN UPDATE SET
dest.phone = src.phone,
dest.phone_ext = src.phone_ext,
dest.beg_date = '10/29/2019',
dest.ofc_add_by = 'TEST'
;
DROP TABLE phone_data;
It might be better/safer to create the temp table explicitly rather than to use the INTO TEMP clause. The types are not necessarily what you'd expect (CHAR(6), CHAR(12), VARCHAR(1), CHAR(4)) — though that may not matter.
Clearly, once the temp table exists, you can insert whatever data is appropriate into the temp table using any mechanism that's available:
INSERT INTO phone_data(id, phone, phone_ext, aa) VALUES(?, ?, ?, ?)
Remember that temp tables are private to a session — you can have lots of people all using the same temporary table name at the same time without interfering with each other.

Oracle ProC INSERT INTO VALUES ( (select ...) )

Running Pro*C on Oracle 10g.
I am looking to do a subquery within an insert statement values clause. This sql query is fully valid and runs within TOAD with no problems, but Pro*C fails to parse the query.
EXEC SQL INSERT INTO TARGET_ATTACHMENT
(
TARGET_ID
FILENAME
)
VALUES (
:targetID,
( SELECT CREATED_FLAG from TARGET t where t.TARGET_ID = :targetID ) || '.tif'
)
If I remove:
( SELECT (CREATED_FLAG || DISPLAY_ID) from TARGET t where t.TARGET_ID = :targetID ) ||**".
The Pro*C compiler works and everything compiles and runs as expected.
If I DO NOT remove:
The Pro*C compiler throws a syntax error.
1>Syntax error at line 128, column 12, file d:\SVN\...\TA.pc:
1>Error at line 128, column 12 in file d:\SVN\...
1>...\TA.pc
1> ( select CREATED_FLAG from target t where t.TARGET_ID = :targetID )
1>...........1
1>PCC-S-02201, Encountered the symbol "CREATED_FLAG" when expecting one of the fol
1>lowing:
1> ( ) * + - / . # | at, day, hour, minute, month, second, year,
This is a problem, as I expect Pro*C to be able to compile subquerys within a values caluse:
ie.
INSERT into table1 (col1) values ( (select t2.singleCol from table2 t2 where t2.priKey = :priKey) )
Is this expected behaviour of Pro*C? or Should it support subqueries within the values clause?
Possibly change the subquery to:
( SELECT CREATED_FLAG || '.tif' from TARGET t where t.TARGET_ID = :targetID )
I dont think I have ever seen something appended to a subquery the way you were attempting.
The amount of SQL the Pro*C preprocessor is able to parse in static SQL statements is quite limited. For example it can't even parse explicit inner joiner/outer left join etc. notation.
As a workaround you can just prepare a dynamic SQL statement and execute it - even if your SQL statement is not really dynamic.
The code you have posted is logically identical to this:
INSERT INTO TARGET_ATTACHMENT
( TARGET_ID , FILENAME )
select :targetID, CREATED_FLAG|| '.tif'
from TARGET t
where t.TARGET_ID = :targetID )
Is there a particular reason why you need to use scalar cursors in a VALUES clause?

How can I update a record using a correlated subquery?

I have a function that accepts one parameter and returns a table/resultset. I want to set a field in a table to the first result of that recordset, passing in one of the table's other fields as the parameter. If that's too complicated in words, the query looks something like this:
UPDATE myTable
SET myField = (SELECT TOP 1 myFunctionField
FROM fn_doSomething(myOtherField)
WHERE someCondition = 'something')
WHERE someOtherCondition = 'somethingElse'
In this example, myField and myOtherField are fields in myTable, and myFunctionField is a field return by fn_doSomething. This seems logical to me, but I'm getting the following strange error:
'myOtherField' is not a recognized OPTIMIZER LOCK HINTS option.
Any idea what I'm doing wrong, and how I can accomplish this?
UPDATE:
Based on Anil Soman's answer, I realized that the function is expecting a string parameter and the field being passed is an integer. I'm not sure if this should be a problem as an explicit call to the function using an integer value works - e.g. fn_doSomething(12345) seems to automatically cast the number to an string. However, I tried to do an explicit cast:
UPDATE myTable
SET myField = (SELECT TOP 1 myFunctionField
FROM fn_doSomething(CAST(myOtherField AS varchar(1000)))
WHERE someCondition = 'something')
WHERE someOtherCondition = 'somethingElse'
Now I'm getting the following error:
Line 5: Incorrect syntax near '('.
I have never done anything like this so .... all the code I have seen uses a schema on the function name - so something like:
FROM dbo.fn_doSomething(myOtherField)
seems like a compiler bug in SQL 2000
try in Server 2005 and join the table-valued function using CROSS APPLY or OUTER APPLY
also try this, guru huys
CREATE FUNCTION FCN_pruebaChicaBorrame(#numerito int)
RETURNS #returnTable TABLE (numerito int)
AS
BEGIN
insert into #returnTable values(#numerito)
return
END
Select * from FCN_pruebaChicaBorrame(20)
Select col_1
from ( select 1 as col_1
union select 2
union select 3) as tablita
Select col_1, (select * from dbo.FCN_pruebaChicaBorrame(20) as fcnTable)
from ( select 1 as col_1
union select 2
union select 3) as tablita
Select col_1, (select * from dbo.FCN_pruebaChicaBorrame(col_1) as fcnTable)
from ( select 1 as col_1
union select 2
union select 3) as tablita
Select col_1, (select * from dbo.FCN_pruebaChicaBorrame(case when 1=1 then 20 else 21) as fcnTable)
from ( select 1 as col_1
union select 2
union select 3) as tablita
I searched on google for this error and one person talks about missing single quotes in search condition. Is that the case with your function code? link to related blog
It seems that (at least in SQL Server 2000) you can't pass a column value to a table valued function. I had to set up a scalar function to get around this.

How can I copy a record, changing only the id?

My table has a large number of columns. I have a command to copy some data - think of it as cloning a product - but as the columns may change in the future, I would like to only select everything from the table and only change the value of one column without having to refer to the rest.
Eg instead of:
INSERT INTO MYTABLE (
SELECT NEW_ID, COLUMN_1, COLUMN_2, COLUMN_3, etc
FROM MYTABLE)
I would like something resembling
INSERT INTO MYTABLE (
SELECT * {update this, set ID = NEW_ID}
FROM MYTABLE)
Is there a simple way to do this?
This is a DB2 database on an iSeries, but answers for any platform are welcome.
You could do this:
create table mytable_copy as select * from mytable;
update mytable_copy set id=new_id;
insert into mytable select * from mytable_copy;
drop table mytable_copy;
I don't think this is doable entirely within SQL without going to the trouble of creating a temp table. Doing it in memory should be much faster. Beware if you go the temporary table route that you must choose a unique name for your table for each function invocation to avoid the race condition where your code runs twice at the same time and mangles two rows of data into one temp table.
I don't know what kind of language you're using but it should be possible to obtain a list of fields in your program. I would do it like this:
array_of_field_names = conn->get_field__list;
array_of_row_values = conn->execute ("SELECT... ");
array_of_row_values ["ID"] = new_id_value
insert_query_string = "construct insert query string from list of field names and values";
conn->execute (insert_query_string);
Then you can encapsulate that as a function and just call it specifying table, old id and new id and it'd work it's magic.
In Perl code the following snippet would do:
$table_name = "MYTABLE";
$field_name = "ID";
$existing_field_value = "100";
$new_field_value = "101";
my $q = $dbh->prepare ("SELECT * FROM $table_name WHERE $field_name=?");
$q->execute ($existing_field_value);
my $rowdata = $q->fetchrow_hashref; # includes field names
$rowdata->{$field_name} = $new_field_value;
my $insq = $dbh->prepare ("INSERT INTO $table_name (" . join (", ", keys %$rowdata) .
") VALUES (" . join (", ", map { "?" } keys %$rowdata) . ");";
$insq->execute (values %$rowdata);
Hope this helps.
Ok, try this:
declare #othercols nvarchar(max);
declare #qry nvarchar(max);
select #othercols = (
select ', ' + quotename(name)
from sys.columns
where object_id = object_id('tableA')
and name <> 'Field3'
and is_identity = 0
for xml path(''));
select #qry = 'insert mynewtable (changingcol' + #othercols + ') select newval' + #othercols;
exec sp_executesql #qry;
Before you run the "sp_executesql" line, please do "select #qry" to see what the command is that you're going to run.
And of course, you may want to stick this in a stored procedure and pass in a variable instead of the 'Field3' bit.
Rob
Your example should almost work.
Just add the column names of the new table to it.
INSERT INTO MYTABLE
(id, col1, col2)
SELECT new_id,col1, col2
FROM TABLE2
WHERE ...;
i've never worked with db2 but in mssql you could solve it with following procedure. this solution only works if you dont care what new id the items get.
1.) create new table with same scheme but where the id column incrementes automatically. (mssql "identitity specification = 1, identity increment = 1)
2.) than a simple
insert into newTable(col1, col2, col3)
select (col1, col2, col3) from oldatable
should be enough, be sure not to include your id colum in the above statement