My Stack Trace
java.sql.SQLSyntaxErrorException: Unknown column 'i' in 'field list'
5 minutes later my Stack Trace was
Named parameter lastName not bound
What is the problem in this query?
My interface
public interface InstructorDao extends JpaRepository <Instructor, Long> {
#Query (nativeQuery=true, value ="select i from Instructor as i where i.firstName like %:firstName% or i.lastName like %:firstName%")
List <Instructor> findInstructorByfirstName (#Param ("firstName") String firstName);
My entity
#Entity
#Table (name = "Instructor")
public class Instructor {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "instructor_id", nullable = false)
private Long instructorId;
#Basic
#Column (name = "name", nullable = false, length = 45)
private String firstName;
#Basic
#Column (name = "lastName", nullable = false, length = 45)
private String lastName;
#Basic
#Column (name = "summary", nullable = false, length = 45)
private String instructorSummary;
#OneToMany (mappedBy = "instructor", fetch = FetchType.LAZY)
private Set <Course> courses = new HashSet<>(); 'i' in 'field lis
Also, if anybody knows where I can find all material about different SQL languages, I will be very grateful, because sometimes professionals write
select i from Instructor as i where i.firstName like %:firstName% or i.lastName like %:firstName% or
select i from Instructor as i where i.user.userEmail =:userEmail or
select * from courses as c where c.course_id in (select e.course_id from enrolled_in as e where e.student_id = :studentId)
I must know all these combinations!
As you specified the query as the native query so you will have to use * to select all.
select * from table i
OR
Select i.* from table i
Related
I am trying to create Dynamic SQL query using Table Function, so that it can be consumed in ABAP CDS views. For same I have developed an ABAP Class & defined a method "Get_data".
CLASS-METHODS get_data FOR TABLE FUNCTION ztablefunction.
I am expecting below results, I am getting table names from field .
for each Condition record number it should go to its respective table and fetch few fields.
NOTE: Every table will have different structures only Condition
Record no. will always be available, e.g. Table A900 may have Sales
Org field, but A912 might not have Sales Org field
Below image depicts data in Dynamic Tables (Table Fields in Table A)
Below image depicts output I am expecting.
CLASS zcl_fiori_test DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
CLASS-METHODS get_data FOR TABLE FUNCTION ztablefunction.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_fiori_test IMPLEMENTATION.
METHOD get_data BY DATABASE FUNCTION
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zcds_test dd03l.
declare tabnamearr string;
declare lv_knumharr string;
declare iv_count integer;
declare i integer;
declare lv_query string;
declare lv_kunnr string;
declare lv_vkorg string;
it_cdhdr = select :p_mandt as client,
conditiontype as cond_type,
'' as valid_start,
'' as valid_end,
changedocobjectclass,
changedocobject,
changedocument,
changetransactioncode,
cdhdrcreationdate,
creationdate,
keycombcondrec from zcds_test;
select count( * ) into iv_count from :it_cdhdr;
it_sel = select changedocobject, keycombcondrec from :it_cdhdr;
it_final1 = select
'' as mandt,
'' as kappl,
' ' as kschl,
' ' as vkorg,
'' as vtweg,
' ' as kunnr,
'' as matnr,
'' as kfrst,
'' as datbi,
'' as datab,
'' as kbstat,
' ' as knumh
from dummy;
it_kunnr = select ' ' as knumh, ' ' as kunnr from dummy;
it_vkorg = select ' ' as knumh, ' ' as vkorg from dummy;'''
for i in 1..iv_count do
tabnamearr = :it_sel.keycombcondrec[i] ;
lv_knumharr = :it_sel.changedocobject[i];
IF exists(select *
from dd03l
where tabname = tabnamearr
and fieldname = 'KUNNR'
) then
lv_kunnr = 'select knumh, kunnr from ' || tabnamearr || ' where knumh = ' || lv_knumharr;
EXECUTE immediate lv_kunnr INTO it_kunnr;
END if;
it_cdsview1 = SELECT a.changedocobjectclass,
a.changedocobject,
a.changedocument,
a.changetransactioncode,
a.cdhdrcreationdate,
a.creationdate,
a.keycombcondrec,
cust.kunnr
from zcds_test as a
left join :it_kunnr as cust on a.changedocobject = cust.knumh;
if exists(select *
from dd03l
where tabname = tabnamearr
and fieldname = 'VKORG'
) then
lv_vkorg = ' it_vkorg = select knumh, vkorg from ' || tabnamearr || ' where knumh = ' || lv_knumharr;
EXECUTE immediate lv_vkorg into it_vkorg;
END if;
it_cdsview2 = SELECT a.changedocobjectclass,
a.changedocobject,
a.changedocument,
a.changetransactioncode,
a.cdhdrcreationdate,
a.creationdate,
a.keycombcondrec,
salesorg.vkorg from zcds_Test as a
left join :it_vkorg as salesorg on a.changedocobject = salesorg.knumh;
end for;
return
select <from Final Output table that should be matched with structure of Table Function>
ENDMETHOD.
ENDCLASS.
Above code, I am not able to store data in temporary table as it does not support.
For alternative I have created structure/table using DUMMY table.
But data is getting replaced with new data.
It might be a wrong approach, kindly suggest correct approach to achieve same.
Please let me know, if you need more information
I have here a query that select from a local variable. It is working fine with my other stored procedures that didn't have array parameter and when I applied it to this stored procedure it is now not working.
Here is my script below.
AS
DECLARE #serverpath varchar(255)
DECLARE #query varchar(max)
BEGIN
SET #serverpath = (SELECT [path] from [param] where [platform] = 'PLMS')
SET #query='
SELECT
''PLMS'' as PLATFORM,
''PLMS''+ ''0''+ordh_sysrefno as ZINDEX,
ad_sapcode AS "SAP ADVERTISER CODE",
ad_advcde AS "PLMS ADVERTISER CODE",
ad_advnme AS "ADVERTISER NAME",
ag_sapcode AS "SAP AGENCY CODE",
ag_agencde AS "PLMS AGENCY CODE",
ag_agennme AS "AGENCY NAME",
ordh_docno AS "TO NUMBER",
ordh_createdate AS "TO CREATE DATE",
ordh_conttp AS "CONTRACT TYPE",
tt_desc AS "TELECAST TYPE",
'''' AS "PACKAGE TYPE",
'''' AS "REVENUE TYPE",
sapcode as "SAP PROGRAM CODE",
pg_prgcode as "PLMS PROGRAM CODE",
pg_prgname as "PROGRAM",
ordd_teledte AS "TELECAST DATE",
ordd_agencost AS "INTERNAL COST",
ordd_billcost AS "BILLING COST",
''PHP'' AS CURRENCY,
'''' AS PRODUCTION,
spd_cpno as "CP NUMBER",
cph_cpdte as "CP DATE",
cph_prndte as "CP PRINT DATE",
CASE ordh_conttp
WHEN ''C''
THEN spd_invno
WHEN ''X''
THEN spd_exinvno
WHEN ''P''
THEN spd_pbinvno
ELSE '''' END AS "INVOICE NUMBER",
spd_stat as "STATUS"
from
' + #serverpath +'.ord_hdr INNER JOIN
' + #serverpath +'.ord_dtl ON (ordh_sysrefno = ordd_sysrefno) INNER JOIN
' + #serverpath +'.spot_dtl ON (ordd_sysrefno = spd_sysrefno and ordd_dtlno = spd_dtlno ) INNER JOIN
' + #serverpath +'.program ON (pg_prgcode = ordd_prgcode ) INNER JOIN
' + #serverpath +'.advertiser ON (ad_advcde = ordh_advcde) INNER JOIN
' + #serverpath +'.agency ON (ag_agencde = ordh_agencde) INNER JOIN
' + #serverpath +'.cp_hdr ON (ordh_sysrefno = cph_refno and spd_cpno = cph_cpno) INNER JOIN
' + #serverpath +'.cp_dtl ON (cph_cpno = cpd_cpno and cpd_dtlno = ordd_dtlno and cpd_spotno = spd_spotno) FULL OUTER JOIN
' + #serverpath +'.telecast_type ON (ordd_teletp = tt_code) left outer join
PLMSSAP.PLMSSAPSU.programs_season on (platform = ''PLMS'' and pg_prgcode = PLMScode and
cpd_teledte BETWEEN date_start AND date_end)
WHERE
cpd_cpno in (Select LTRIM(RTRIM(StringValue)) FROM #StringAsArray)
'
EXEC (#query)
END
and this is my c# script
public static DataTable SelectFromLocal(string stdproc, string name, DataTable cps)
{
DataTable dt = new DataTable();
dt.TableName = name;
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["BMSSAP"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(stdproc, con))
{
cmd.CommandType = CommandType.StoredProcedure;
var param = new SqlParameter();
param.SqlDbType = SqlDbType.Structured;
param.Value = cps;
param.TypeName = "StringArray";
param.ParameterName = "#StringAsArray";
cmd.Parameters.Add(param);
cmd.CommandTimeout = 60 * 60 * 60;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
sda.Fill(dt);
}
}
}
return dt;
}
and I got this error every time I run my application
System.Data.SqlClient.SqlException`: 'Must declare the table variable "#StringAsArray"'.
The problem here is one of scope. Wikipedia has a very detailed definition of scope here. If you want a quick summary, this isn't terrible.
You have dynamic-SQL in your code. By that I mean you are building a SQL statement as a string, and then executing the string using exec().
When you do that, everything inside the exec() is running in its own scope. It can't see any variables that were declared outside of the string you created.
Here's a simple example
declare #var varchar(20) = 'hello'; -- this is in the outer scope
exec
(
'select #var;' -- this will run in its own scope
);
What will happen when I run that? Do I get the result "hello"? No, the variable #var was only declared in the outer scope. In the inner scope it has not been declared. So I get an error:
Must declare the scalar variable "#var".
But just declaring it doesn't help, I want to pass the variable from the outer scope to the inner scope. This won't do what I want:
declare #var varchar(20) = 'hello'
exec('declare #var varchar(20); select #var');
That will run without causing an error, but the result will be null. The #var inside the string is not associated with the #var in the outer scope.
What I need to do is bind the outer #var to the inner one. You can do this with the sp_executesql procedure. THe following code will do what I want. It will output "hello":
declare #var varchar(20) = 'hello';
exec sp_executesql
N'select #var', -- the first argument is the statement I want to run
N'#var varchar(20)', -- the second argument is a comma separated string of parameter definitions
#var; -- the subsequent arguments map the variables from the outer scope to the parameter definitions
I am not going to write out the entire construct for your case, because your dynamic SQL statement is very long. But you have an identical situation. You have a variable which lives in the outer scope as a table valued parameter. You want to send that variable into the scope of the dynamic SQL.
create type dbo.MyStringArray as table (MyString varchar(20));
go
create or alter procedure MyProcedure (#MyTvp dbo.MyStringArray readonly) as
begin
declare #dynamicSQL nvarchar(max) = 'select MyString from #MyTvp';
exec sp_executesql
#dynamicSQL,
N'#MyTvp dbo.MyStringArray readonly',
#MyTvp;
end;
go
-- I can now call this using:
declare #t dbo.MyStringArray;
insert #t values ('hello');
exec myProcedure #t;
NOTE that you must declare the variable which will hold your dynamic SQL as NVARCHAR, not VARCHAR, in order to use sp_executesql. Same with the parameter definitions. If you prefix a literal string with the letter N, it is an nvarchar (as in my example).
I have several drop-down lists with item-value pairs on front-end side. Let's say in the first ddl(animals) - dog has value 1, cat - 2, ANY - 0, in the second ddl(colors) - black color has value 1, white - 2 and ANY - 0.
Also I would like to use stored procedure to select the data from db by the values selected in drop-downs.
So, the result should be filtered only in case of value != 0. in case of 0 the result should not be filtered.
The best solution what I can imagine is to create SELECT query on code side (w/o SP):
string animalParam = ddl_animal.SelectedValue.Equals("0") ? "1 = 1" : $" animal_id={ddl_animal.SelectedValue}";
string colorParam = ddl_color.SelectedValue.Equals("0") ? "AND 1 = 1" : $"AND color={ddl_color.SelectedValue}";
string query = $"SELECT * FROM table WHERE {animalParam} {colorParam}";
But is it good enough? Or there is a better way to do this e.g. on SP side? Using default values somehow?
Thanks in advance!
Your solution should work, but you can also move the logic into SQL if you prefer to:
CREATE PROCEDURE dbo.FilterByColorAndAnimal
(
#AnimalId INT = 0,
#ColorId INT = 0
)
AS
BEGIN
DECLARE #SQL = N'
SELECT *
FROM table W
WHERE 1 = 1'
IF (#AnimalTypeId <> 0) SET #SQL = #SQL + ' AND animal_id = #AnimalId'
IF (#ColorId <> 0) SET #SQL = #SQL + ' AND color_id = #ColorId'
EXEC sp_executesql #SQL, '#AnimalId INT, #ColorId INT', #AnimalId, #ColorId
END
GO
Alternatives:
do not use dynamic SQL, but a more convoluted query involving ORs
SELECT *
FROM table W
WHERE (#AnimalId = 0 OR animal_id = #AnimalId)
AND (#ColorId = 0 OR color_id = #ColorId)
use LINQ2SQL with EntityFramework
var query = context.Table;
int animalId = Convert.ToInt32(ddl_animal.SelectedValue);
if (animalId != 0)
query = query.Where(item => item.animal_id = animalId);
int colorId = Convert.ToInt32(ddl_color.SelectedValue);
if (colorId != 0)
query = query.Where(item => item.color_id = colorId);
This will generate the most efficient query (similar to your initial solution).
I have Below sp.
ALTER procedure [dbo].[stpxxxx]
#ID int = null,
#FKcomID int = null,
#type int = 1
as
begin
IF (#type = 1)
BEGIN
----query A
SELECT Member.PKID, Member.FKID, Person.ID, Member.FKID, Member.StartDate
FROM Member INNER JOIN
Person ON Member.FKID = Person.PKID
WHERE (Person.ID = #ID)AND (Member.FKID = #FKcomID)
end
ELSE
BEGIN
----query B
SELECT pre.PKID, pre.FKID, pre.FKPersonID
FROM pre INNER JOIN
Person ON pre.FKID = person.PKID
WHERE (Person.ID = #ID) AND (pre.FKID = #FKcomID)
end
if (#type = 1) there was a error
Conversion failed when converting the nvarchar value '900905 ' to data type int.
If I swap the query A and B it aslo gettion erroe with IF (#type = 1).
what is wrong with my Sp.
If you do an LTRIM(RTRIM()) on the value, it will work; there is a space causing the issue.
It appears to be an issue with whitespace.
Try this:
LTRIM(RTRIM())
on the offending value.
I am new to databases, so it might be it is very easy.
I have the following database structure:
Table products
Table filters (could contain something like)
Color blue
Color black
Color red
Size small
Brand X
Table relation (has only product id and filter id)
Lets say I want to obtain all products that are black or red and are small, I wrote the following query:
SELECT products.name FROM products
JOIN pfrelation ON
((pfrelation.filter_id=18) AND (pfrelation.filter_id=11 OR pfrelation.filter_id=13) AND products.id=pfrelation.product_id)
In the the example above 11 and 13 represent black and red, while 18 is the id for small. As you might suspect the above query has no results (the id can not be both 18 and 11/13). How can I write the select in order to dynamically add any combination of filters? How can I rewrite the query in the example above?
Thank you
you can achieve this with Dynamic Query.
I don't much know about PostgreSql, but I know SQL Server, so I am giving a example to do same.
Here is SQLFiddel Demo
Create table Product(pid int,name varchar(10),color varchar(10),brand varchar(10),size varchar(10));
insert into product values(1,'ABC','red','X','small');
create table pfrelation(pid int,fid int,relation varchar(100));
insert into pfrelation values(1,10,'Color=''blue''');
insert into pfrelation values(1,11,'Color=''black''');
insert into pfrelation values(1,13,'Color=''red''');
insert into pfrelation values(1,18,'size=''small''');
insert into pfrelation values(1,20,'brand=''X''');
Declare #sql varchar(200)
select #sql = ((select 'pr.' + relation from pfrelation where fid = 18)
+ ' and (' +
(select 'pr.' + relation from pfrelation where fid = 11)
+ ' or ' +
(select 'pr.' + relation from pfrelation where fid = 13)
+ ') and pr.pid=pf.pid' )
select #sql
print('select * from Product pr,pfrelation pf where '+#sql)
exec('select * from Product pr,pfrelation pf where '+#sql)
I build the query dynamically this way:
public ArrayList<Products> getFilteredOnlinePictures( Hashtable<String, List<String>> filters,..)
{
SQLiteDatabase db = getWritableDatabase();
// create query conditions
StringBuffer filtersQuery = new StringBuffer();
for (String key: Collections.list(filters.keys()))
{
List<String> filtersValues = filters.get(key);
if (filtersQuery.length() > 0)
filtersQuery.append(" INTERSECT ");
filtersQuery.append("SELECT " + TABLE_PFRELATIONS + "." + COLUMN_PRODUCT_ID
+ " FROM " + TABLE_PFRELATIONS + " WHERE " + TABLE_PFRELATIONS + "."
+ COLUMN_FILTER_ID + " IN (");
for (String value: filtersValues)
{
long filterID = getIDForFilter(db, key, value);
filtersQuery.append(filterID);
if (filtersValues.indexOf(value) == (filtersValues.size() - 1))
{
// this is the last value
filtersQuery.append(")");
}
else
{
// there are more values
filtersQuery.append(",");
}
}
}
if (filtersQuery.length() > 0)
{
filtersQuery.append(")");
filtersQuery.insert(0, " WHERE " + TABLE_PRODUCTS + ".id" + " IN (");
}
String sql = "SELECT " + TABLE_PRODUCTS + "." + COLUMN_NAME + " FROM " + TABLE_PRODUCTS + filtersQuery.toString();
Cursor c = db.rawQuery(sql, null); ...
The query given as an example will be:
SELECT products.name FROM products
WHERE products.id IN (
SELECT pfrelation.product_id FROM pfrelation WHERE pfrelation.filter_id IN (18)
INTERSECT
SELECT pfrelation.product_id FROM pfrelation WHERE pfrelation.filter_id IN (11,13)
)
This way I could have any filter with any number of values.