Stored Procedure doesn't bring results - java

My stored procedure isn't bringing results as it should
All parameters are set OK, like my table name (that is variable according to the year/month).
When I execute the query manually on Management Studio, the results come, but when I call the procedure on my Controller, it doesn't.
PS: the code executed directly is with other dates, but the code executed in the IDE with the informed dates should had brought a result too, I've tried with different dates, the problem seems to be in the Stored Procedure query.
STORED PROCEDURE CODE:
ALTER PROCEDURE [dbo].[usp_listarRegistrosMov]
--PARĂ‚METROS
#NomeTabela VARCHAR(20),
#DataInicial VARCHAR(20),
#DataFinal VARCHAR(20),
#Cracha FLOAT
AS
BEGIN
Declare #Comando Varchar(1000)
Set #Comando = 'SELECT * FROM ' + #NomeTabela + ' WHERE mov_data BETWEEN ' + #DataInicial + ' AND ' + #DataFinal + ' AND mov_cracha = ' + CAST(#Cracha AS VARCHAR(20))
Exec(#Comando)
END
GO
CONTROLLER CODE:
public void consultar() {
LocalDate dataInicio = dataInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate dataFim = dataFinal.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
String mesInicio = String.valueOf(dataInicio.getMonthValue());
String mesFim = String.valueOf(dataFim.getMonthValue());
String anoInicio = (String.valueOf(dataInicio.getYear())).substring(2,4);
String anoFim = (String.valueOf(dataFim.getYear())).substring(2,4);
String empresaString = String.valueOf(Math.round(funcionario.getEmpresa().getCodigo()));
long mesesDiferencaGlob = ChronoUnit.MONTHS.between(dataInicio, dataFim) + 1;
if (dataInicio.isAfter(dataFim)) {
Messages.addGlobalError("Informe uma data inicial posterior Ă  data final");
return;
}
if (dataInicio.getMonthValue() != dataFim.getMonthValue()) {
if (dataInicio.getYear() == dataFim.getYear()) {
do {
System.out.println(mesesDiferencaGlob);
String tabela = ("M00"+(String.valueOf(Math.round(funcionario.getEmpresa().getCodigo())))+anoInicio+"0"+mesInicio);
System.out.println(tabela);
DateTimeFormatter formatadorInicio = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String dataInicioString = dataInicio.format(formatadorInicio);
String dataFimString = dataFim.format(formatadorInicio);
System.out.println(dataInicioString + dataFimString);
setRegistrosTemp(eventoEspelhoPontoRepository.findAllRegistrosByFuncionarioTableUnica(tabela, dataInicioString, dataFimString, funcionario.getCracha()));
for (EventoEspelhoPonto item : registrosTemp) {
registros.add(item);
}
int mesInicioInt = Integer.parseInt(mesInicio) + 1;
mesInicio = Integer.toString(mesInicioInt);
mesesDiferencaGlob--;
} while (mesesDiferencaGlob != 0);
}
}
}
REPOSITORY CODE:
#Query(value = "EXECUTE usp_listarRegistrosMov :tabela, :dataInicial, :dataFinal, :cracha", nativeQuery = true)
List<EventoEspelhoPonto> findAllRegistrosByFuncionarioTableUnica(#Param("tabela") String tabela,
#Param("dataInicial") String dataInicial,
#Param("dataFinal") String dataFinal,
#Param("cracha") Double cracha);

In your stored procedure, because you're using strings for dates in a dynamic sql string, you need to add 2 single quotes around them so that the string that gets executed will enclose them in single quotes.
In other words, change this:
Set #Comando = 'SELECT * FROM ' + #NomeTabela +
' WHERE mov_data BETWEEN ' + #DataInicial + ' AND ' + #DataFinal + ' AND mov_cracha = ' + CAST(#Cracha AS VARCHAR(20))
to this:
Set #Comando = 'SELECT * FROM ' + #NomeTabela +
' WHERE mov_data BETWEEN ''' + #DataInicial + ''' AND ''' + #DataFinal + ''' AND mov_cracha = ' + CAST(#Cracha AS VARCHAR(20))
I don't promise that's your only problem because I don't speak java, but that is definitely a problem in your stored procedure.

Related

Modifying SQLite Search Parameters to Return Full String From One Word Instead of Specific Order

I am having trouble with altering the search parameters within SQLite, currently, the search functions that I have for searching film titles and genres can only return the specific result, e.g., Action will only bring back Action films and not Action, Adventure films.
I have had a friend manage to have it work within the SQLite Studio itself, but using this method has been unsuccessful. He suggested using the following ORDER BY, however, it still gives the same results.
Cursor c = sqdb.rawQuery("SELECT * FROM filmography WHERE genre LIKE '%" + searchGenre + "' ORDER BY LENGTH(genre) ASC",
null);
I am at a loss now as I cannot seem to come across or figure out the answer. How would I go about changing the SQL so that if you were to search say "Action" in the genre search, it would bring back all results so eg., "Film 1 = Action, Film 2 = Action, Adventure, Film 3 = Action, Crime" and so on?
Example of genre data: "Capone, Biography, Crime, Drama, Fonse, 2020, 4.7/10
Black Hawk Down, Drama, History, War, Twombly, 2001, 7.7/10
Venom, Action, Adventure, Sci-Fi, Eddie Brock / Venom, 2018, 6.7/10
public String searchByTitleInFilmography(SQLiteDatabase sqdb, String searchfilmTitle)
{
String result = "";
Cursor c = sqdb.rawQuery("SELECT * FROM filmography WHERE filmTitle = '" + searchfilmTitle + "'",
null);
if (c != null)
{
if (c.moveToFirst())
{
do
{
String id = c.getString(0);
result = result + id + ": ";
String filmtitle = c.getString(1);
result = result + "Title: " + filmtitle + ". ";
String genre = c.getString(2);
result = result + "Genre(s): " + genre + ". ";
String role = c.getString(3);
result = result + "Role: " + role + ". ";
String year = c.getString(4);
result = result + "Released: " + year + ". ";
String imdbrating = c.getString(5);
result = result + "Rating: " + imdbrating + "\n" + "\n";
Log.w("FILM_TITLE_GENRE", "ID - " + id +":" + " Genre(s) = " + genre);
} while (c.moveToNext());
}
else
{
result = "No Films Found With The Title = " + searchfilmTitle;
}
}
c.close();
return result;
} // public String serachByTitleInFilmography(SQLiteDatabase sqdb, String searchTitle)
If the column genre contains values like a comma separated list of genres, then you should change the operand of the operator LIKE like this:
String sql = "SELECT * FROM filmography WHERE ',' || REPLACE(genre, ', ', ',') || ',' LIKE '%,' || ? || ',%'"
Cursor c = sqdb.rawQuery(sql, new String[] {searchGenre});
REPLACE() removes all spaces after each comma and each value of genre becomes like: ',Action,Crime,Drama,'.
When you pass 'Action' as the parameter for the ? placeholder then the sql statement becomes:
SELECT * FROM filmography WHERE ',Action,Crime,Drama,' LIKE '%,Action,%'
which is what you want: all the rows that contain 'Action' anywhere in the column genre.

get a custom query result containing Clob in Java Spring App

I need to get a very long string from Oracle DB in Spring App, but using a function returning clob leads to internal server error 500. How to get a custom query result containing Clob?
PL/SQL function returning a very long string in clob:
create or replace function getVeryLongString(id_ in number)
return clob as
CURSOR cur IS select x.TARGET || ' pX=' || x.px as tpx -- to get concat string in order of PX desc
from (
select distinct a.ID,
a.TARGET,
MAX(a.PX) OVER (PARTITION BY a.TARGET, a.ID) as px
from BA_ACTIVITYDATA A
where A.TARGET is not null
and a.ID = id_
order by px desc
) x;
l_data clob := '';
begin
FOR fld IN cur
LOOP
l_data := l_data || fld.tpx || ' | ';
end loop;
return rtrim( l_data, ' | ');
end
;
I use this function in Query in Java Spring app:
public interface TargetRepository extends JpaRepository<List, Long> {
#Query(
value = "select t1.fieldA,\n" +
" t1.fieldB,\n" +
" t2.fieldC,\n" +
" getVeryLongString(t3.value1) as fieldD\n" +
"from tableA t1\n" +
"join tableB t2 on t1.id = t2.id\n" +
"join tableC t3 on t3.id = t2.id\n" +
"where t.id = :id",
nativeQuery = true
)
DataTypePX getDataById(Long id);
}
TargetActivity interface looks like:
public interface DataTypePX {
String getFIELDA();
String getFIELDB();
String getFIELDC();
String getFIELDD();
}
Using the above code leads to 500 ERROR.
to fix it I need to change function getVeryLongString as returning varchar2 - it works, but it leads to cutting of result string only to 4000 symbols:
create or replace function getVeryLongString(id_ in number)
return varchar2 as
CURSOR cur IS select x.TARGET || ' pX=' || x.px as tpx -- to get concat string in order of PX desc
from (
select distinct a.ID,
a.TARGET,
MAX(a.PX) OVER (PARTITION BY a.TARGET, a.ID) as px
from BA_ACTIVITYDATA A
where A.TARGET is not null
and a.ID = id_
order by px desc
) x;
-- l_data varchar2(32767) := '';
l_data clob := '';
begin
FOR fld IN cur
LOOP
l_data := l_data || fld.tpx || ' | ';
end loop;
return rtrim( substr(l_data, 1, 4000), ' | ');
end;

Call SQL function from Java

I have a begin end block in SQL and I did something like this to call it from Java, but when I check if it executes correctly it gives me an error like this :
Missing IN or OUT parameter at index:: 1 Error Code: 17041
My code is this :
public void setDate(){
String startDate = null, endDate = null;
Query query = manager.createNativeQuery("Declare "
+ "dStartDate date := ADD_MONTHS( sysdate, - 60);"
+ "begin "
+ "schema.table.SetDateLimits( dStartDate, ADD_MONTHS( sysdate, - 1));"
+ ":END := To_Char(SYSDATE,'yyyy/mm');"
+ ":START := To_Char(dStartDate,'yyyy/mm');" + "end;");
Object v = query.getSingleResult();
System.out.println("The limits are " + startDate+ " " +endDate);
}
Does anybody know why? Thanks in advance!

Updating SQL Table with Java

I am developing an application that can update my database... However, I can't get my Java method working correctly. It gives me the following error: Must declare the scalar variable "#P0WHERE". Any suggestions?
The method I am using:
public void updateTable() throws SQLException
{
Scanner input = new Scanner(System.in);
System.out.println("Update the following:\n" + this);
this.getReservationInfo(input);
DataConnection connection = new DataConnection();
String query = "UPDATE " + TableName;
query += "Set Name = ?";
query += "WHERE Person_ID = " + id;
connection.updateData(query, person_name);
connection.closeConnection();
}
Add spaces before 'SET' and 'WHERE', otherwise it will not work.
String query = "UPDATE " + TableName;
query += " SET Name = ?";
query += " , Age = ?";
query += " , Col1 = ?"; //And other cols
query += " WHERE Person_ID = " + id;
EDIT: Changed query to update multiple columns.
I think so. You seem to be missing spaces. After the TableName and after the ?.
String query = "UPDATE " + TableName;
query += " Set Name = ?"; // tableSet not good, and
// ?WHERE is not valid add spaces.
query += " WHERE Person_ID = " + id;

Avoid query duplication when 'IN list' which empty and non empty list

public static final String UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_SQL = "\n" +
"UPDATE document d \n" +
"SET d.indexed = :flagValue \n" +
"WHERE d.user_id = :userId \n" +
"AND d.to_delete = :toDelete";
public static final String UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_WITH_EXCEPTIONS_SQL = "\n" +
"UPDATE document d \n" +
"SET d.indexed = :flagValue \n" +
"WHERE d.user_id = :userId \n" +
"AND d.to_delete = :toDelete \n" +
"AND d.id NOT IN (:exceptForDocuments)";
public int markUserDocumentsToDeleteAsUnindexed(String userId,Collection<String> exceptForDocuments) {
Map<String,Object> params = Maps.newHashMap();
params.put("flagValue",false);
params.put("userId",userId);
params.put("toDelete",1);
params.put("exceptForDocuments",exceptForDocuments);
if ( exceptForDocuments.isEmpty() ) {
return jdbcTemplate.update(UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_SQL, params);
}
else {
return jdbcTemplate.update(UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_WITH_EXCEPTIONS_SQL,params);
}
}
Is there a way to use a single query to perform both updates?
Because actually using the UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_WITH_EXCEPTIONS_SQL query seems to work against H2, but not MySQL.
Any idea to avoid this query duplication?
The problem is likely because not every driver can handle parameterized arrays/collections. If you have complete control over the exceptForDocuments contents, you can serialize it to SQL yourself (with simple sanitization checks) and then conditionally append it without using parameters.

Categories