I have looked and looked, mostly at UPDATE with multiple tables. Once or twice I searched specificially with 5 tables. The examples mostly show only two tables.
When I run the code below I get this message:
update for memret 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(M.first = test, M.last = nine, M.address1 = 999 woodland, M.zip = 21122, M.emai' at line 5
From my research this happens to many. I have switched around the code numerous times. This is my latest stab at what might fly but it crashed with the same message as above.
This code is below followed by the mysql db record.
Help please!
$sql = "UPDATE membership AS M
LEFT JOIN address2 AS A2 ON M.memno1 = A2.memno2
LEFT JOIN contact AS Con ON M.memno1 = Con.memno3
LEFT JOIN workers AS W ON M.memno1 = W.memno4
LEFT JOIN comments AS Com ON M.memno1 = Com.memno5";
$sql.=" SET (M.first = $first, M.last = $last, M.address1 = $address1,";
$sql.=" M.zip = $zip, M.email = $email, M.password = $password,";
$sql.=" M.secq = $secq,M.seca = $seca,";
$sql.=" A2.address2 = $address2,";
$sql.=" Con.home = $home, Con.cell = $cell, Con.work = $work,";
$sql.=" W.webhelp = $webhelp, W.locorg = $locorg, W.candasst = $candasst,";
$sql.=" W.loccam = $loccam, W.other = $other, W.otherexp = $otherexp,";
$sql.=" Com.comment = $comment) WHERE memno1=$memno";
$result = mysql_query($sql) or die("update for memret 1: ".mysql_error());
memno1 first last address1 zip email password secq seca memno2 address2 memno3 home cell work memno4 webhelp locorg candasst loccam other otherexp memno5 comment memno6 office first last address1 address2 zip
9 test nine 999 woodland 21122 tn9#aol.com tn9999 house wreck 9 dump 9 1232224444 333556666 2223335555 9 yes yes ceo 9 test new side
This is an SQL injection. If I read the error message correctly, $address1 is "999 woodland" which will not be treated correctly by the SQL parser.
Stop substituting raw variables into query strings. (And stop using mysql_* functions, too. They're deprecated.) A prepared statement will go a long way here.
// assumes an existing PDO database connection in $conn
// requires exception-handling code (PDOException)
// requires you to check that e.g. integer fields will be updated with integers
$sql = "UPDATE membership AS M
LEFT JOIN address2 AS A2 ON M.memno1 = A2.memno2
LEFT JOIN contact AS Con ON M.memno1 = Con.memno3
LEFT JOIN workers AS W ON M.memno1 = W.memno4
LEFT JOIN comments AS Com ON M.memno1 = Com.memno5
SET (M.first = :first, M.last = :last, M.address1 = :address1,
M.zip = :zip, M.email = :email, M.password = :password,
M.secq = :secq, M.seca = :seca,
A2.address2 = :address2,
Con.home = :home, Con.cell = :cell, Con.work = :work,
W.webhelp = :webhelp, W.locorg = :locorg, W.candasst = :candasst,
W.loccam = :loccam, W.other = :other, W.otherexp = :otherexp,
Com.comment = :comment) WHERE memno1 = :memno";
$query = $conn->prepare($sql);
$params = array(":first" => $first, ":last" => $last, ":address1" => $address1,
":zip" => $zip, ":email" => $email, ":password" => $password,
":secq" => $secq, ":seca" => $seca,
":address2" => $address2,
":home" => $home, ":cell" => $cell, ":work" => $work,
":webhelp" => $webhelp, ":locorg" => $locorg,
":candasst" => $candasst,
":loccam" => $loccam, ":other" => $other,
":otherexp" => $otherexp,
":comment" => $comment, ":memno" => $memno);
$did_we_succeed = $query->execute($params);
Related
I'm trying to create a custom list for my module on Prestashop 1.6 and I need to get data from three different tables. My problem is the $this->_filter variable, how can I do that?
I need to do this:
$query = '
SELECT s.*, pl.*
FROM '._DB_PREFIX_.'`scd_gift` s
INNER JOIN '._DB_PREFIX_.'product_lang pl
ON s.id_product = pl.id_product
WHERE s.`id_gift_type` = '.(int)$id_gift_type.' and id_lang='.$id_lang;
Here is my function:
public function getCustomListHostessGifts() {
$this->table = 'scd_gift';
$this->list_id = 'hostess_gift';
$this->lang = true;
$this->identifier = 'id_scd_gift';
$this->_orderBy = 'id_product';
$this->_orderWay = 'DESC';
$this->addRowAction('delete');
$this->fields_list = (array(
'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs',
'align' => 'center'),
'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name'),
));
$this->clearFilters();
$hostessType = MlmGiftsModule::getGiftTypeIdByGiftTypeName('_HOSTESSGIFT_');
$this->_join = Shop::addSqlAssociation('scd_gift', 'a');
$this->_filter = '
INNER JOIN '._DB_PREFIX_.'product_lang pl
ON s.id_product = pl.id_product
AND a.`id_gift_type` ='.$hostessType ;
$this->toolbar_title = $this->l('Hostess gifts:');
return $this->renderList();
}
_filter is use to set filter parameters passed in backoffice list search fields.
Any JOIN sentence must be set in _join var:
$this->_join = Shop::addSqlAssociation('scd_gift', 'a');
. ' INNER JOIN '._DB_PREFIX_.'product_lang pl
ON s.id_product = pl.id_product
AND a.`id_gift_type` ='.$hostessType ;
Good luck.
PixelWeb's answer is correct, but of course, there is no semicolon after
$this->_join = Shop::addSqlAssociation('scd_gift', 'a')
Additional. You may skip this line anyway, because Prestashop adds the default SQL association "a" for the table in the controller itsself.
I have a set of related tables that I am trying to return a result set for and I just can't get the syntax quite right to get the results I want.
I am trying to return a list of countries (United States being the only one expected right now) with appropriate states. The "appropriate" requirement is that I only want to return the states under the countries that are represented by one of our clients....ie....if we have 3 clients, 2 in Texas and 1 in OK, I need the query to return "United States (with only Texas and OK...not the other 48 states where we don't have clients).
I can get the query to return only the United States, but it returns ALL states, not just the ones I am after. This is an example of the query that I "want" to run....NOTE: FirstAdminDivision table = states table.
select * from Country c
inner join FirstAdminDivision f on f.CountryId = c.CountryId
where f.FirstAdminDivisionId IN
(
select f2.FirstAdminDivisionId from Company C
inner join [Address] a on a.AddressId = c.AddressId
inner join City cty on cty.CityId = a.CityId
inner join FirstAdminDivision f2 on f2.FirstAdminDivisionId = cty.FirstAdminDivisionId
)
This is the code I currently have (which is as close as I have been able to get) that returns the US only with all states. The "ids" list contains only Texas and OK like I would expect, so I think they issue lies in the where in the main select.
IQueryable<int> innerQ = base.Context.Set<FirstAdminDivision>().Where(x => x.Cities.Any(y => y.Addresses.Any(z => z.Companies.Any()))).Select(x => x.FirstAdminDivisionId);
List<int> ids = innerQ.ToList();
IQueryable<ICountryModel> q2 = base.Context.Set<Country>()
.Include(x => x.FirstAdminDivisions)
.Where(x => x.FirstAdminDivisions.Where(y => innerQ.Contains(y.FirstAdminDivisionId)).Any())
.Select(x => new CountryModel
{
Abbreviation = x.Abbreviation,
CountryId = x.CountryId,
Name = x.Name,
UrlDisplay = x.UrlDisplay,
FirstAdminDivisions = x.FirstAdminDivisions.Select(y => new FirstAdminDivisionModel
{
Abbreviation = y.Abbreviation,
Name = y.Name,
UrlDisplay = y.UrlDisplay
}).ToList()
});
Any help pointing out what I am missing/doing wrong would be greatly appreciated.
Well basically i would use your first query as the base query instead of all the countries and instead of returning a list of ints i would want it to return a list of FirstAdminDivision objects.
So in this case you would have two objects in that list OK and Texas. And in this case you also should have the country available since you say that FirstAdminDivision has the country as a property
Then from that list i would include country object so you can group those two state objects by country. And from that build your model using the key, country, and then the list of states.
Something like this:
IQueryable<ICountryModel> countriesWithStates = base.Context.Set<FirstAdminDivision>()
.Where(x => x.Cities.Any(y => y.Addresses.Any(z => z.Companies.Any())))
.Include(x => x.Country)
.GroupBy(x => x.Country, y=>y, (countryKey, states) => new { Country = countryKey, States = states.ToList() })
.Select(x => new CountryModel
{
Abbreviation = x.Country.Abbreviation,
CountryId = x.Country.CountryId,
Name = x.Country.Name,
UrlDisplay = x.Country.UrlDisplay,
FirstAdminDivisions = x.States.Select(y => new FirstAdminDivisionModel
{
Abbreviation = y.Abbreviation,
Name = y.Name,
UrlDisplay = y.UrlDisplay
}).ToList()
});
Here is the original logic
(scrape_datas = ScrapeData.find(
:all, :conditions =>
"artist_status = 'NOT_FOUND'
AND blacklisted = 1
AND extracted = 0
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
I've been able to split up the first part better
scrape_datas = ScrapeData.where(
:artist_status => 'NOT_FOUND',
:blacklisted => 1,
:extracted => 0
)
Although having issues getting the "and not EXISTS" query into the mix
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
Thanks!
Firstly you can extract simple scopes:
scope :not_found, where(:artist_status => 'NOT_FOUND')
scope :blacklisted, where(:blacklisted => 1)
scope :extracted, where(:extracted => 0)
Then add a query method (assume artist_name is a column of scrape_datas):
def self.no_suggestions
scrape_datas = ScrapeData.arel_table
suggestions = ArtistNameSuggestion.arel_table
where(ArtistNameSuggestion.where(
suggestions[:original].eq(scrape_datas[:artist_name])
).exists.not)
end
Now you can do something like this:
ScrapeData.not_found.blacklisted.extracted.no_suggestions
Basically I crossed the same problem of Linq provider in this linq-to-nhibernate-produces-unnecessary-joins
List<Competitions> dtoCompetitions;
dtoCompetitions = (from compset in session.Query<FWBCompetitionSet>()
where compset.HeadLine == true
&& compset.A.B.CurrentSeason == true
select (new Competitions
{
CompetitionSetID = compset.CompetitionSetID,
Name = compset.Name,
Description = compset.Description,
Area = compset.Area,
Type = compset.Type,
CurrentSeason = compset.A.B.CurrentSeason,
StartDate = compset.StartDate
}
)).ToList();
Which leads to duplicated join in its generated SQL
SELECT fwbcompeti0_.competitionsetid AS col_0_0_,
fwbcompeti0_.name AS col_1_0_,
fwbcompeti0_.DESCRIPTION AS col_2_0_,
fwbcompeti0_.area AS col_3_0_,
fwbcompeti0_.TYPE AS col_4_0_,
fwbseason3_.currentseason AS col_5_0_,
fwbcompeti0_.startdate AS col_6_0_
FROM fwbcompetitionset fwbcompeti0_
INNER JOIN A fwbcompeti1_
ON fwbcompeti0_.competitionseasonid = fwbcompeti1_.competitionseasonid
INNER JOIN A fwbcompeti2_
ON fwbcompeti0_.competitionseasonid = fwbcompeti2_.competitionseasonid
INNER JOIN B fwbseason3_
ON fwbcompeti2_.seasonid = fwbseason3_.seasonid
WHERE fwbcompeti0_.headline = #p0
AND fwbseason3_.currentseason = #p1
Notice these joins, which are totally duplicated and also affect my SQL Server's performence.
INNER JOIN A fwbcompeti1_
ON fwbcompeti0_.competitionseasonid = fwbcompeti1_.competitionseasonid
INNER JOIN A fwbcompeti2_
ON fwbcompeti0_.competitionseasonid = fwbcompeti2_.competitionseasonid
Update1
In the NHibernate 3.2, this LiNQ bug is still valid, and I could not find a simple and reasonable Linq solution.
So I used QueryOver + JoinAlias + TransformUsing finishing the job, workds perfect to me.
FWBCompetitionSet compset = null;
FWBCompetitionSeason compseason = null;
FWBSeason season = null;
IList<Competitions> dtoCompetitions;
dtoCompetitions = session.QueryOver<FWBCompetitionSet>(() => compset)
.JoinAlias(() => compset.FWBCompetitionSeason, () => compseason)
.JoinAlias(() => compseason.FWBSeason, () => season)
.Where(() => compset.HeadLine == true)
.And(() => season.CurrentSeason == true)
.SelectList(
list => list
.Select(c => c.CompetitionSetID).WithAlias(() => compset.CompetitionSetID)
.Select(c => c.Name).WithAlias(() => compset.Name)
.Select(c => c.Description).WithAlias(() => compset.Description)
.Select(c => c.Area).WithAlias(() => compset.Area)
.Select(c => c.Type).WithAlias(() => compset.Type)
.Select(c => season.CurrentSeason).WithAlias(() => season.CurrentSeason)
.Select(c => c.StartDate).WithAlias(() => compset.StartDate)
)
.TransformUsing(Transformers.AliasToBean<Competitions>())
.List<Competitions>();
Yet Another Edit:
I think I finally found out what's going on. It seems that the LINQ to NHibernate provider has trouble navigating associations from the target to the source table and generates a separate join each time it encounters such an association.
Since you don't provide your mapping, I used the mapping from linq-to-nhibernate-produces-unnecessary-joins. This model has a Document with one Job and many TranslationUnits. Each TranslationUnit has many Translation entities.
When you try to find a Translation based on a Job, you are traversing the associations in the reverse order and the LINQ provider generates multiple joins: one for Translation -> TranslationUnit and one for TranslationUnit to Document.
This query will generate redundant joins:
session.Query<TmTranslation>()
.Where(x => x.TranslationUnit.Document.Job == job)
.OrderBy(x => x.Id)
.ToList();
If you reverse the navigation order to Document -> TranslationUnit -> Translation, you get a query that doesn't produce any redundant joins:
var items=(from doc in session.Query<Document>()
from tu in doc.TranslationUnits
from translation in tu.Translations
where doc.Job ==job
orderby translation.Id
select translation).ToList();
Given this quirkiness, QueryOver seems like a better option.
Previous Edit:
I suspect the culprit is compset.A.B.CurrentSeason. The first joined table (fwbcompeti1_) returns A.B while the next two (fwbcompeti2_ and fwbseason3_) are used to return A.B. The LINQ to NHibernate provider doesn't seem to guess that A is not used anywhere else and fails to remove it from the generated statement.
Try to help the optimizer a little by replacing CurrentSeason = compset.A.B.CurrentSeason with CurrentSeason = true from the select, since your where statement returns only items with CurrentSeason == true.
EDIT: What I mean is to change the query like this:
List<Competitions> dtoCompetitions;
dtoCompetitions = (from compset in session.Query<FWBCompetitionSet>()
where compset.HeadLine == true
&& compset.A.B.CurrentSeason == true
select (new Competitions
{
CompetitionSetID = compset.CompetitionSetID,
Name = compset.Name,
Description = compset.Description,
Area = compset.Area,
Type = compset.Type,
CurrentSeason = true,
StartDate = compset.StartDate
}
)).ToList();
I simply replace the value compset.A.B.CurrentSeason with true
How can I join two tables from different dataases using nhibernate ConfORM or at least write sql query in nhibernate ConfORM?
This is the query which I need to run:
select RTRIM(l.descr) as affiliation, a.LocationId
from Facilities a
join [tmt-sam2].sammi.dbo.location l ON a.LocationId = l.off_code+'-'+l.location
Thanks,
Alexey
if you dont have that many locations you can strait load all
using (var session1 = sessionfactoryDataBase1.OpenSession())
using (var session2 = sessionfactory_tmt_sam2.OpenSession())
{
var locations = session2.QueryOver<Location>().List();
var results = session1.QueryOver<Facility>()
.Where(f => f.LocationId.IsIn(locations.Select(l => l.OffCode + '-' + l.location)))
.AsEnumerable()
.Join(locations, f => f.LocationId, l => l.OffCode + '-' + l.location, (f, l) => new { Description = l.descr.TrimEnd(), LocationId = f.LocationId });
}
otherwise batches in the code