Am using a dynamic query to get data. Below is my code
if(objVal != null){
sObject obj = Schema.getGlobalDescribe().get(objVal).newSObject();
if(ConditionVal== null || ConditionVal=='')
query = 'Select Id From '+objVal+ ' Limit 10000';
else{
ConditionVal= String.escapeSingleQuotes(ConditionVal);
query = 'Select Id From '+selectedObj+' WHERE '+ConditionVal+' LIMIT 10000';
}
List<SObject> objlst = Database.query(query);
Am getting "objVal" , "ConditionVal" value form VF page
Example objVal = 'Account' ConditionVal = 'industry = 'Apparel'
after executing the code am getting the query like this
Select Id From Account WHERE industry = \'Apparel\' LIMIT 10000
update the value of ConditionVal variable as below,
ConditionVal = 'Industry = \'Apparel\'';
the query will work as expected.
Related
I'm working through a stored procedure and wondering if there's a way to retrieve the anticipated result column list from a sql statement before fully executing.
Scenarios:
dynamic SQL
a UDF that might vary the columns outside of our control
EX:
//inbound parameter
SET QUERY_DEFINITION_ID = 12345;
//Initial statement pulls query text from bank of queries
var sqlText = getQueryFromQueryBank(QUERY_DEFINITION_ID);
//now we run our query
var cmd = {sqlText: sqlText };
stmt = snowflake.createStatement(cmd);
What I'd like to be able to do is say "right - before you run this, give me the anticipated column list" so I can compare it to what's expected.
EX:
Expected: [col1, col2, col3, col4]
Got: [col1]
Result: Oops. Don't run.
Rationale here is that I want to short-circuit the execution if something is missing - before it potentially runs for a while. I can validate all of this after the fact, but it would be really helpful to stop early.
Any ideas very much appreciated!
This sample SP code shows how to get a list of columns that a query will project into the result before you run the query. It should only be used for large, long running queries because it will take a few seconds to get the column list.
There are a couple of caveats. 1) It will only return the names of the columns. It won't tell you how they were built, that is, whether they're aliased, direct from a table, calculated, etc. 2) The example query I used is straight from the Snowflake documentation here https://docs.snowflake.com/en/user-guide/sample-data-tpcds.html#functional-query-definition. For convenience, I minimized the query to a single line. The output of the columns includes object qualifiers in addition to the column names, so V1.I_CATEGORY, V1.D_YEAR, V1.D_MOY, etc. If you don't want them to make it easier to compare names, you can strip off the qualifiers using the JavaScript split function on the dot and take index 1 of the resulting array.
create or replace procedure EXPLAIN_BEFORE_RUNNING()
returns string
language javascript
execute as caller
as
$$
// Set the context for the session to the TPC-H sample data:
executeNonQuery("use schema snowflake_sample_data.tpcds_sf10tcl;");
// Here's a complex query from the Snowflake docs (minimized to one line for convienience):
var sql = `with v1 as( select i_category, i_brand, cc_name, d_year, d_moy, sum(cs_sales_price) sum_sales, avg(sum(cs_sales_price)) over(partition by i_category, i_brand, cc_name, d_year) avg_monthly_sales, rank() over (partition by i_category, i_brand, cc_name order by d_year, d_moy) rn from item, catalog_sales, date_dim, call_center where cs_item_sk = i_item_sk and cs_sold_date_sk = d_date_sk and cc_call_center_sk= cs_call_center_sk and ( d_year = 1999 or ( d_year = 1999-1 and d_moy =12) or ( d_year = 1999+1 and d_moy =1)) group by i_category, i_brand, cc_name , d_year, d_moy), v2 as( select v1.i_category ,v1.d_year, v1.d_moy ,v1.avg_monthly_sales ,v1.sum_sales, v1_lag.sum_sales psum, v1_lead.sum_sales nsum from v1, v1 v1_lag, v1 v1_lead where v1.i_category = v1_lag.i_category and v1.i_category = v1_lead.i_category and v1.i_brand = v1_lag.i_brand and v1.i_brand = v1_lead.i_brand and v1.cc_name = v1_lag.cc_name and v1.cc_name = v1_lead.cc_name and v1.rn = v1_lag.rn + 1 and v1.rn = v1_lead.rn - 1) select * from v2 where d_year = 1999 and avg_monthly_sales > 0 and case when avg_monthly_sales > 0 then abs(sum_sales - avg_monthly_sales) / avg_monthly_sales else null end > 0.1 order by sum_sales - avg_monthly_sales, 3 limit 100;`;
// Before actually running the query, generate an explain plan.
executeNonQuery("explain " + sql);
// Now read the column list from the explain plan from the result set.
var columnList = executeSingleValueQuery("COLUMN_LIST", `select "expressions" as COLUMN_LIST from table(result_scan(last_query_id())) where "operation" = 'Result';`);
// For now, just exit with the column list as the output...
return columnList;
// Your code here...
// Helper functions:
function executeNonQuery(queryString) {
var out = '';
cmd = {sqlText: queryString};
stmt = snowflake.createStatement(cmd);
var rs;
rs = stmt.execute();
}
function executeSingleValueQuery(columnName, queryString) {
var out;
cmd1 = {sqlText: queryString};
stmt = snowflake.createStatement(cmd1);
var rs;
try{
rs = stmt.execute();
rs.next();
return rs.getColumnValue(columnName);
}
catch(err) {
if (err.message.substring(0, 18) == "ResultSet is empty"){
throw "ERROR: No rows returned in query.";
} else {
throw "ERROR: " + err.message.replace(/\n/g, " ");
}
}
return out;
}
$$;
call Explain_Before_Running();
With my select below, if blank string is passed in I get the following error: Null or empty full-text predicate
in my DBAdapter when fetching rows from the database. If I provide a value, such as Well, I do not get results when I should as Well is in the r.[Desc] column. If I pass in Well One, I get: Syntax error near 'one' in the full-text search condition 'Well one'.
If I pass in One, I get nothing.
I've read similar questions here and have not seen a pattern where the value passed in can be nothing, the beginning of the column data, a word in the middle of the column data or more than one word in any order of the column data. I thought Contains returns the row if the column contains the value or part of the value passed in.
What am I doing wrong?
if #Drawing = ''
set #Drawing = null
if #ItemName = ''
set #ItemName = null
if #CF3 = ''
set #CF3 = null
if #Desc = ''
set #Desc = null
if #Design = ''
set #Design = null
if #MaxPSI = 0
set #MaxPSI = null
Select distinct
,r.[DRAWING]
,r.[DESC]
,r.[OP_PSI]
,r.[MAX_PSI]
,r.[MAX_TEMP]
,r.[Insulated]
,r.[DESIGN]
From Ref r
inner join Eng e on e.[DRAWING] = r.[DRAWING]
where r.SurveyNumber = #SurveyNumber
And (rtrim(#Drawing) is NUll or rtrim(r.DRAWING) like rtrim(#Drawing) + '%')
And (rtrim(#Design) is NUll or rtrim(r.DESIGN) like rtrim(#Design) + '%')
And (rtrim(#MaxPSI) is NUll or rtrim(r.MAX_PSI) like rtrim(#MaxPSI) + '%')
And (rtrim(#CF3) is NUll or rtrim(e.CF3) like rtrim(#CF3) + '%')
And (rtrim(#ItemName) is NUll or rtrim(e.ITEM_NAME) like rtrim(#ItemName) + '%')
AND ((#Desc = '""') OR CONTAINS( (r.[Desc]), #Desc))
I think you can try checking for empty as follows:
AND ((#Desc = '""' OR #Desc = '') OR CONTAINS( (r.[Desc]), #Desc))
I suspect the empty predicate may be getting passed as '' instead of "".
Have not used Contains much but from section in the doc [here][1] it seems you either need operators between the words or need to wrap expression in double quotes "". So what you can do is try passing params like this:
AND ((#Desc = '""' OR #Desc = '') OR CONTAINS( (r.[Desc]), '"'+#Desc+'"'))
What possible purpose is
rtrim(#Drawing) is NUll
If it is NULL the rtrim has no meaning. Besides comparison of string basically does an rtrim.
I need to convert this SQL Query to Link :
"Select * FROM [Register]
where RegisterId IN (SELECT MyId
FROM Friends
WHERE FriendId='" + Session["CurrentProfileId"] + "'
AND Status=1
UNION
SELECT FriendId
FROM Friends
WHERE MyId='" + Session["CurrentProfileId"] + "'
AND Status=1) ";
It may be look like this??? but this is incorrect and having errors
(from u in db.Register
where RegisterId).Contains
(from f in db.Freinds
where f.MyId == Id && m.Status == 1
select new { m.MyId })
.Union(from m in db.Freinds
where f.FreindId == Id && m.Status == 1
select new { m.CreateDate } ));
You have a few problems with the linq above and here are a few:
In the query in the Union you select the CreateDate whereas in the top on you select the MyId. I assume you meant to select FreindId.
In these 2 queries you create an anonymous class instance with the field but then compare it to the RegisterId which is probably a guid/string/int - but for sure not of the type you just created.
You are using the Contains method wrong. Linq syntax can be similar to sql but it is not the same. Check here for Contains
The correct Linq way of doing it is:
var idsCollection = ((from f in db.Freinds
where f.StatusId == 1 && f.MyId == Id
select f.MyId)
.Union(from m in db.Friends
where m.StatusId == 1 && f.FreindId == Id
select m.FriendId)).ToList();
var result = (from u in db.Register
where idsCollection.Contains(u.RegisterId)
select u).ToList();
Notice that the .ToList() is not a must and is here just to ease in debugging. For more information about this .ToList() and Linq in general check MSDN
I have an object with number of records in this format with Name in Text format -
Id Name
1 A,B,C
2 A,B
3 A
4 B
5 A,C
6 A,D
I have a multi-select picklist with values as:
A
B
C
D
So if I select B and C in my picklist, then I must have the records from the table in which name consists of B or C or (B and C) i.e. in this case, it should show 4 records:
1 A,B,C
2 A,B
4 B
5 A,C
I am using SQL query with IN and INCLUDES keyword but I am unable to achieve this functionality.
This depends on how many options you have for using soql. One way I can see it is:
Object__c myObject = new Object__c();
object.Name = 'A,B,D';
object.Multi_Select_Name__c = 'A;E';
insert object;
String query = 'select Id from Object__c';
//now we want to do a multi picklist, which is a String separated by ';'
List<String> nameSelections = object.Multi_Select_Name__c.split(';');
if(nameSelections.size() > 0) {
query += ' where ';
for(Integer i = 0; i < nameSelections.size(); i++) {
nameSelections[i] = 'Name like \'%' + nameSelections[i] + '%\'';
}
query += String.join(nameSelections, ' or ');
}
List<Object__c> objects = (List<Object__c)database.query(query);
This will create a query like:
'select Id from Object__c where Name like '%A%' or Name like '%E%'
Selecting all Object__c's where Name contains either A or E, generated from your multiselect.
Syntax errors may apply, I just wrote this real quick :) Ill double check myself.
EDIT:
This code works to build the query
String query = 'select Id from Object__c';
String multiSelect = 'A;E';
List<String> nameSelections = multiSelect.split(';');
if(nameSelections.size() > 0 ){
query += ' where ';
for(Integer i = 0; i < nameSelections.size(); i++) {
nameSelections[i] = 'Name like \'%' + nameSelections[i] + '%\'';
}
query += String.join(nameSelections, ' or ');
}
system.debug(LoggingLevel.INFO, query);
i am doing this:
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("datapath") = dpath
.Fields("analysistime") = atime
.Fields("reporttime") = rtime
.Fields("lastcalib") = lcalib
.Fields("analystname") = aname
.Fields("reportname") = rname
.Fields("batchstate") = bstate
.Fields("instrument") = instrument
.Update ' stores the new record
End With
' get the last id
Set rs = cn.Execute("SELECT SCOPE_IDENTITY()", , adCmdText)
this is not working properly. it is returning NULL
It's not working because your updates and your second execute are in different scopes.
You may want SELECT IDENT_CURRENT('tablename')
IDENT_CURRENT is fine in a single user environment.
You're already on the record when you update.
.Update
lTheNewID = .Fields("ThisTableID")
lTheNewID will hold the value of the new record.