implementing oracle query to powerbuilder - oracle

I have difficulty in implementing Oracle query to powerbuilder. I have 3 singeline edit the name is :
1. sle_merk
2. sle_tipe
3. sle_jns
and I have oracle query
select b.nm_merk
, c.keterangan
, c.tipe
, b.keterangan
, c.usrid
, c.otr
, c.dupd
, c.dotr
, c.status
from tipe_kend c
left
outer
join jns_kendaraan b
on c.kd_jenis = b.kd_jenis
left
outer
join merk_kend b
on c.kd_merk = b.kd_merk
where b.kd_jenis like '%%'
AND b.kd_merk like '%%'
AND c.tipe like '%%'
what I want is if all singeline edit is null then the data is appears, but when one of singeline edit is filled then the data is appears where data like %singelineedit%. I have difficulty in implementing the query into Powerbuilder.

Since you don't say you are using a datawindow control I will assume you are not. With that being said then this must be a piece of embedded SQL inside some method. As such you need to declare variables for each of the columns in your retrieve. You also need variables to hold the contents of the SLE controls.
You would end up with something like this:
string ls_nm // make sure datatypes are correct
string ls_sle1, ls_sle2, ls_sle3
// get values of the sle controls
ls_sle1 = sle_merk.text
IF IsNull(ls_sle1) THEN ls_sle1 = ''
ls_sle2 = sle_tipe.text
IF IsNull(ls_sle2) THEN ls_sle2 = ''
ls_sle3 = sle_jns.text
IF IsNull(ls_sle3) THEN ls_sle3 = ''
select b.nm_merk, ...
INTO :ls_nm, ...
from tipe_kend c
left outer join ns_kendaraan b on c.kd_jenis = b.kd_jenis
left outer join merk_kend b on c.kd_merk = b.kd_merk
where b.kd_jenis like '%' + ls_sle1 + '%'
AND b.kd_merk like '%' + ls_sle2 + '%'
AND c.tipe like '% + ls_sle3 + '%';
Note this will FAIL if more than a single row is returned. If you need multiple rows you need to use a datawindow/datastore control (or cursors but they are very inefficient).

Related

Load only some elements of a nested collection efficiently with LINQ

I have the following LINQ query (using EF Core 6 and MS SQL Server):
var resultSet = dbContext.Systems
.Include(system => system.Project)
.Include(system => system.Template.Type)
.Select(system => new
{
System = system,
TemplateText = system.Template.TemplateTexts.FirstOrDefault(templateText => templateText.Language == locale.LanguageIdentifier),
TypeText = system.Template.Type.TypeTexts.FirstOrDefault(typeText => typeText.Language == locale.LanguageIdentifier)
})
.FirstOrDefault(x => x.System.Id == request.Id);
The requirement is to retrieve the system matching the requested ID and load its project, template and template's type info. The template has multiple TemplateTexts (one for each translated language) but I only want to load the one matching the requested locale, same deal with the TypeTexts elements of the template's type.
The LINQ query above does that in one query and it gets converted to the following SQL query (I edited the SELECT statements to use * instead of the long list of columns generated):
SELECT [t1].*, [t2].*, [t5].*
FROM (
SELECT TOP(1) [p].*, [t].*, [t0].*
FROM [ParkerSystems] AS [p]
LEFT JOIN [Templates] AS [t] ON [p].[TemplateId] = [t].[Id]
LEFT JOIN [Types] AS [t0] ON [t].[TypeId] = [t0].[Id]
LEFT JOIN [Projects] AS [p0] ON [p].[Project_ProjectId] = [p0].[ProjectId]
WHERE [p].[SystemId] = #__request_Id_1
) AS [t1]
LEFT JOIN (
SELECT [t3].*
FROM (
SELECT [t4].*, ROW_NUMBER() OVER(PARTITION BY [t4].[ReferenceId] ORDER BY [t4].[Id]) AS [row]
FROM [TemplateTexts] AS [t4]
WHERE [t4].[Language] = #__locale_LanguageIdentifier_0
) AS [t3]
WHERE [t3].[row] <= 1
) AS [t2] ON [t1].[Id] = [t2].[ReferenceId]
LEFT JOIN (
SELECT [t6].*
FROM (
SELECT [t7].*, ROW_NUMBER() OVER(PARTITION BY [t7].[ReferenceId] ORDER BY [t7].[Id]) AS [row]
FROM [TypeTexts] AS [t7]
WHERE [t7].[Language] = #__locale_LanguageIdentifier_0
) AS [t6]
WHERE [t6].[row] <= 1
) AS [t5] ON [t1].[Id0] = [t5].[ReferenceId]
which is not bad, it's not a super complicated query, but I feel like my requirement can be solved with a much simpler SQL query:
SELECT *
FROM [Systems] AS [p]
JOIN [Templates] AS [t] ON [p].[TemplateId] = [t].[Id]
JOIN [TemplateTexts] AS [tt] ON [p].[TemplateId] = [tt].[ReferenceId]
JOIN [Types] AS [ty] ON [t].[TypeId] = [ty].[Id]
JOIN [TemplateTexts] AS [tyt] ON [ty].[Id] = [tyt].[ReferenceId]
WHERE [p].[SystemId] = #systemId and tt.[Language] = 2 and tyt.[Language] = 2
My question is: is there a different/simpler LINQ expression (either in Method syntax or Query syntax) that produces the same result (get all info in one go) because ideally I'd like to not have to have an anonymous object where the filtered sub-collections are aggregated. For even more brownie points, it'd be great if the generated SQL would be simpler/closer to what I think would be a simple query.
Is there a different/simpler LINQ expression (...) that produces the same result
Yes (maybe) and no.
No, because you're querying dbContext.Systems, therefore EF will return all systems that match your filter, also when they don't have TemplateTexts etc. That's why it has to generate outer joins. EF is not aware of your apparent intention to skip systems without these nested data or of any guarantee that these systems don't occur in the database. (Which you seem to assume, seeing the second query).
That accounts for the left joins to subqueries.
These subqueries are generated because of FirstOrDefault. In SQL it always requires some sort of subquery to get "first" records of one-to-many relationships. This ROW_NUMBER() OVER construction is actually quite efficient. Your second query doesn't have any notion of "first" records. It'll probably return different data.
Yes (maybe) because you also Include data. I'm not sure why. Some people seem to think Include is necessary to make subsequent projections (.Select) work, but it isn't. If that's your reason to use Includes then you can remove them and thus remove the first couple of joins.
OTOH you also Include system.Project which is not in the projection, so you seem to have added the Includes deliberately. And in this case they have effect, because the entire entity system is in the projection, otherwise EF would ignore them.
If you need the Includes then again, EF has to generate outer joins for the reason mentioned above.
EF decides to handle the Includes and projections separately, while hand-crafted SQL, aided by prior knowledge of the data could do that more efficiently. There's no way to affect that behavior though.
This LINQ query is close to your SQL, but I'm afraid of correctness of the result:
var resultSet =
(from system in dbContext.Systems
from templateText in system.Template.TemplateTexts
where templateText.Language == locale.LanguageIdentifier
from typeText in system.Template.Type.TypeTexts
where typeText.Language == locale.LanguageIdentifier
select new
{
System = system,
TemplateText = templateText
TypeText = typeText
})
.FirstOrDefault(x => x.System.Id == request.Id);

Dynamic Linq core

Hi I am using a Jqwidgets Grid to display my data. It has a build in possibility to use filters but if you filter your records on the server side you have to build your own query. As I am working with Linq I thought to use the Dynamic Linq Library for Asp net core. Problem is there are not many examples or explanations how to do this. But I am busy for days now and not getting very far.The way I am setup; I have a normal Linq query:
var Mut = from M in _DB.Mutations
join S in _DB.Shifts on M.ShiftId equals S.ShiftId
join U in _DB.RoosterUsers on M.UserId equals U.RoosterUserId
join D in deps on M.UserId equals D.UserId
join DD in _DB.Departements on D.DepartementID equals DD.DepartementId
select new MutationModel
{
MutId=M.MutationId,
Naam=U.FirstName + " " + U.LastName,
UserId=M.UserId,
Departement= DD.DepartementName,
MutationType = S.publicName,
MutationGroup = S.ShiftType.ToString(),
DateTot =M.DateTill,
TijdVan=M.DateStartOn,
TijdTot=M.DateTill,
Status=CreateStatus(M.Tentative, M.ApprovedOn, M.Processed, M.CancelRefId, M.Deleted)
};
This query is running OK and gives me all the data I need for the Grid.
Then for the filter I would like to add a dynamic Linq Query using the System.Linq.Dynamic.Core library
But this is as far as I get things working until now:
var outQuery = Mut.Where("Status = #0 and UserId = #1", "Nieuw", "KLM22940").Select("Status");
My questions now :
1. In the where clause If I make the fieldname variable I get an error. how to do this??
2. In the Select Clause, how to add multiple Columns? (actually I just like to output all columns.)
Best would be to see an example. has somebody used Dynamic Linq to build a dynamic linq query for the JQWidgets Grid?
Thank you very much.
In what way you are trying to use fieldname variable in where clause ?
If you want to output all columns you can use ToList()
like
var outQuery = Mut.Where("Status = #0 and UserId = #1", "Nieuw", "KLM22940").ToList();
If you want to get some specific columns you can use Select clause like this
var outQuery = Mut.Where("Status = #0 and UserId = #1", "Nieuw", "KLM22940").Select("new(Status,UserId )");
This Select clause creates data class which contains Status and UserId properties and returns a sequence of instances of that data class.

Is it safe to use DB :: select and others in Laravel?

Queries are not always simple, and sometimes I need to create a pure SQL query, the query builder also does not fit.
При использовании DB::select, подготовливаются ли
переменные, которые подставлены в запрос?
Will there be a sql injection in this case?
$mastersInCity = DB::select('SELECT
master_user.master_id,
masters.specialization,
category_letter_master.category_letter_id AS master_letter,
COUNT(*) AS count_in_city
FROM master_user
LEFT JOIN masters ON master_user.master_id = masters.id
LEFT JOIN category_letter_master ON category_letter_master.master_id = master_user.master_id
WHERE ' . $chooiseId . ' = ' . $cityId . ' GROUP
BY master_user.master_id, master_letter');
Or, in this case, it is better to use PDO directly, so as to manually prepare the request yourself, is it possible?
$mastersInCity = DB::select('SELECT
master_user.master_id,
masters.specialization,
category_letter_master.category_letter_id AS master_letter,
COUNT(*) AS count_in_city
FROM master_user
LEFT JOIN masters ON master_user.master_id = masters.id
LEFT JOIN category_letter_master ON category_letter_master.master_id = master_user.master_id
WHERE ? = ? GROUP
BY master_user.master_id, master_letter', [$chooiseId, $cityId]);
This is equivalent to a prepared statement.
Docs: https://laravel.com/docs/5.7/database#running-queries
Edit: I am sure this can be done with eloquent simply, there is nothing too complex here. Something like:
MasterUser::with(['master', 'master_letter'])->withCount()->where($chooiseId, $cityId)->get()

Linq Query with multiple joins and multiple conditions

I am using Telerik Data Access to perform OR mapping.
I am trying to use Linq for performing a join query but not sure how to proceed correctly.
The original sql query is given by:
'SELECT O.OPS_LEG_ID, O.ATD_DATE, O.DEP_AIRPORT_ACT, O.ARR_AIRPORT_ACT, O.ATA_DATE, '+
'O.FL_LOG_ATD_DATE, O.FL_LOG_ATA_DATE, O.FL_LOG_DEP_AIRPORT, O.FL_LOG_ARR_AIRPORT, '+
'O.FL_NB, O.DESIGNATOR, O.FL_LOG_ID, O.FL_LOG_STATUS '+
'FROM CREW_ROT_ROLE CR, OPS_LEG O, CREW_ROLES R, CREW_PAIRING_CMP CP '+
'WHERE CR.ROLE_CDE = R.ROLE_CDE '+
'AND CR.CREW_ROTATION_ID = CP.CREW_ROTATION_ID '+
'AND CP.OPS_LEG_ID = O.OPS_LEG_ID '+
'AND CR.CREW_CDE = :CREW_CDE '+
'AND O.ATD_DATE >= :D_FROM '+
'AND O.ATD_DATE <= :D_TO '+
//'AND R.ROLE_TYPE = 0 '+
'ORDER BY O.ATD_DATE
The corresponding Entities have been generated from the SQL tables. I am now trying to build the equivalent Linq query, which does not seem to work:
var results = from opsLeg in dbContext.OPS_LEGs
from crewRotationRole in dbContext.CREW_ROT_ROLEs
from crewRole in dbContext.CREW_ROLEs
from crewPairingComponent in dbContext.CREW_PAIRING_CMPs
where crewRotationRole.ROLE_CDE == crewRole.ROLE_CDE
&& crewRotationRole.CREW_ROTATION_ID == crewPairingComponent.CREW_ROTATION_ID
&& crewPairingComponent.OPS_LEG_ID == opsLeg.OPS_LEG_ID
&& crewRotationRole.CREW_CDE == userId
select new { OpsLegId = opsLeg.OPS_LEG_ID,
Designator = opsLeg.DESIGNATOR,
FlightNumber = opsLeg.FL_NB
};
Trying the previous query, raises an exception:
"Identifier 'ROLE_CDE' is not a parameter or variable or field of
'FlightLogEntities.OPS_LEG'. If 'ROLE_CDE' is a property please add
the FieldAlias or Storage attribute to it or declare it as a field's
alias."
Not sure how to proceed. What would be the correct query using Linq joins? Thanks!
If you are using a ORM like Entity framework, then the conceptual model would be mix of classes, which would provide a object centric view of data.
So, you would be using the Linq on Objects and in that case you need not write queries for joins as we do in SQL for a database. Conceptual model would contain objects which would be having relationships using navigational properties, and to access navigational properties you can access them as a property of object.
For e.g if there are 2 tables in Database, Customer & Orders. Following SQL statement will return all Orders for Customer number 1:
SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
Where Customers.CustomerID = 1
If we use the EF to generate to generate the conceptual model from Database, we would get class for Customer and Order and Customer class would have a property of ICollection. So, if you need the same results as the SQL query above, you would do it in following way
var CustomerOne = context.Customers.Where(x => x.CustomerID == 1);
var ordersForCustomerOne = CustomerOne.Orders;
You can try something like
var k = from r in dataContext.Order_Details
join t in dataContext.Orders on r.OrderID equals t.OrderID
select r.OrderID ;

LINQ - Join only one attribute with whole schema onf another entity

I have two entities smtracks and tracks_registration I write the following linq
var track = from tracksData in sqlEntities.smtracks
join track_registrationData in sqlEntities.tracks_registration on tracksData.TracksID equals track_registrationData.FkTrackId
where tracksData.TracksID == 35 && track_registrationData.TuneCode == 5982234E
select new
{
Tunecode = track_registrationData.TuneCode
};
now i just need this one attribute Tunecode from the other table and rest i want to have the whole schema of smtracks selected. The only way i know is that I select all the attributes in the LINQ above like
select new
{
Tunecode = track_registrationData.TuneCode
TracksID = smtracks.TracksID
SongTitle = smtracks.SongTitle
.
.
.
.
.
};
and there are a lot of attributes, isn't there a simpler way to select the entire schema of one table and the just one attribute from other.
If you don't mind have extra parameter to hold the smtracks, then you can write like this :-
select new
{
smtracks=tracksData ,
Tunecode = track_registrationData.TuneCode
};
Later on you can get the value like smtracks.TracksID and so on.

Resources