SSRS How to see multi value parameter in subscription - sql-server

I tried to get value from query or to specify values, as soon as the parameter is multi value i can't see the data when i'm trying to make my subscription.
my request looks like :
select id from employee where canal in(#canal)
what should i do, i'm totally stuck,
when i did research i saw data driven subscription but i don't have access to it apparently, don't know if that help

I'll start by saying sorry this isn't a pleasant answer. You've run into a limitation with the built-in functionality. Thankfully there are workarounds.
The problem is that you can only pass 1 value into the data-driven subscription. So you have use a comma-separated list and get the query/report to parse out the values.
If you have or can create a Split function in your database, that is a good option. This would be a table-valued user defined function and there are some easy to find examples already. Also this function is generally good to have for other use cases anyway. With this your SQL would read:
where canal in Split(#canal)
SSRS works really well with SQL Server, but when you use an ODBC connection, the parameter support is limited. You can use the same multi-value parameter workaround that is required in those cases.
In the Dataset properties > parameters tab, use an expression like this to combine the values into a single comma-separated string surrounded by commas.
="," + Join(Parameters!canal.Value, ",") + ","
The SQL would look like this:
where # like '%,' + canal + ',%'
Basically, this searches row-by-row for values that are contained in the string.
In either case, the query in your data-driven subscription settings will need to return the comma-separated string. Then you can select that column in the report parameters value field. Hope this helps!

Related

How to get rid of the default single quotes in parameterized queries in clickhouse

Consider this simple program:
from clickhouse_driver import Client
c = Client(host="localhost")
params = {"database": "test", "table": "t"}
query = c.substitute_params( query='SELECT * from %(database)s.%(table)s', params= params, context=c.connection.context)
print(query)
Clickhouse will put single quotes around the parameters, so the query result will be:
SELECT * from 'test'.'t'
I could also use f-string and the problem will be solved but that's vulnerable to SQLI. If I understand correctly, this is how parameterized queries are used in clickhouse to prevent SQLI.
How can we prevent the quotes from being put around the parameters?
As I understand it, substitute_params is not intended for database object identifiers like database and table, since those have to be quoted "differently" in ClickHouse (generally with backticks) than actual literal string values (with single quotes). https://clickhouse.com/docs/en/sql-reference/syntax/#identifiers
In general you can do your own bit of "SQL Injection defense" by validating the inputs for database and table, like ensuring they match a simple regex like "are all lower case letters or underscore" that applies to your ClickHouse schema. In that case using an f-string should be safe.
ClickHouse also support "server side substitution" where you can use an Identifier type for this use case, but I don't believe that feature is available in clickhouse-driver.

Use String parameter for RegEx in query

In my query (the database is a sql server) I use a RegEx for a select command like this:
SELECT * FROM test WHERE id LIKE '1[2,3]'
(This query is tested and returns the data I want)
I want to use a paramter for this RegEx. For that I definded the Paramter in iReport $P{id} as a string and the value is "1[2,3]".
In my query I use now this parameter like this:
SELECT * FROM test WHERE id LIKE $P{id}
As result I get a blank page. I think the problem is that the value of the parameter is defined with " ". But with ' ' I get a compiler error that the paramter isn't a string.
I hope someone can help me.
LIKE applies to text values, not to numeric values. Since id is numeric use something like this:
SELECT * FROM test WHERE id IN (12, 13)
with the parameter
SELECT * FROM test WHERE id IN ($P!{id_list})
and supply a comma separated list of ids for the parameter. The bang (!) makes sure that the parameter will be inserted as-is, without string delimiters.
Btw: LIKE (Transact-SQL) uses wildcards, not regex.
You can still use LIKE since there exists an implicit conversion from numeric types to text in T-SQL, but this will result in a (table or index) scan, where as the IN clause can take advantage of indexes.
The accepted answer works but it is using String replacement, read more about sql-injection, to understand why this is not good practice.
The correct way to execute this IN query in jasper report (using prepared statement) is:
SELECT * FROM test WHERE $X{IN, id, id_list}
For more information as the use of NOTIN, BETWEEN ecc. see JasperReports sample reference for query

MS SQL Excel Query wildcards

I'm trying to introduce LIKE clause with wildcards in SQL query that runs within Excel 2007, where parameters are taken from specific Excel cells:
SELECT Elen_SalesData_View.ItemCode, Elen_SalesData_View.ItemDescription,
Elen_SalesData_View.ItemValue, Elen_SalesData_View.Quantity,
Elen_SalesData_View.CustomerId, Elen_SalesData_View.CustomerName,
Elen_SalesData_View.SalesInvoiceId, Elen_SalesData_View.EffectiveDate,
Elen_SalesData_View.CountryId
FROM SM_Live.dbo.Elen_SalesData_View Elen_SalesData_View
WHERE (Elen_SalesData_View.EffectiveDate>=? And Elen_SalesData_View.EffectiveDate<=?)
AND (Elen_SalesData_View.CustomerName<>'PROMO')
AND (Elen_SalesData_View.ItemDescription LIKE '%'+?+'%')
The EffectiveDate parameters are running fine and bringing back data as expected. But since I introduced LIKE - query runs, but returns nothing.
It doesn't return any results without wildcards either (full description entered):
(Elen_SalesData_View.ItemDescription LIKE ?)
Is there a restriction to wildcards or LIKE clause? If so, is there a way around it? (I cannot use CONTAINS, as the ItemDescription field is not FULLTEXT)
Have a look at this reference which suggests that % itself is the wildcard character, although it may depend on the dialect of SQL you are using. If this is the case then your LIKE clause will simply be LIKE '%' but untested.
I've just got this to work by using the (Elen_SalesData_View.ItemDescription LIKE ?) syntax then having the cell that contains the parameter value include the wildcard characters. If you don't/can't include the wildcards then create a formula in a separate cell to wrap the value in % characters and use this cell for the parameter value.
Rhys
My query was correct. There was something wrong with the actual spreadsheet. After redoing all from scratch - it worked!
SELECT Elen_SalesData_View.ItemCode, Elen_SalesData_View.ItemDescription,
Elen_SalesData_View.ItemValue, Elen_SalesData_View.Quantity,
Elen_SalesData_View.CustomerId, Elen_SalesData_View.CustomerName,
Elen_SalesData_View.SalesInvoiceId, Elen_SalesData_View.EffectiveDate,
Elen_SalesData_View.CountryId
FROM SM_Live.dbo.Elen_SalesData_View Elen_SalesData_View
WHERE (Elen_SalesData_View.ItemDescription Like '%'+?+'%')
AND (Elen_SalesData_View.EffectiveDate>=?) AND (Elen_SalesData_View.EffectiveDate<=?)
AND (Elen_SalesData_View.CustomerName<>'PROMO')

Is it possible to concat strings in SOQL?

I've read thread from 2005 and people said SOQL does not support string concatenation.
Though wondering if it is supported and someone has done this.
I'm trying to concat but no luck :(
Below is APEX code trying to find record with specified email.
String myEmail = 'my#email.com';
String foo = 'SELECT emailTo__c, source__c FROM EmailLog__c
WHERE source__c = \'' +
myEmail + '\';
Database.query(foo)
Even though the record is indeed in the database, it does not query anything. Debug shows
"row(0)" which means empty is returned.
Am I doing concat wrong way?
UPDATE
I just found a way not have to add single quote. Just needed to apply same colon variable even for String that has query.
String foo = DateTime.newInstance(......);
String bar = 'SELECT id FROM SomeObject__c WHERE createdOn__c = :foo';
List<SomeObject__c> result = Database.query(bar);
System.debug(result);
This works too and is necessary if WHERE clause contains DateTime since DateTime cannot be surrounded with single quotes.
Why do you use Database.query()? Stuff will be much simpler and faster if you'll use normal queries in brackets
[SELECT emailTo__c, source__c FROM EmailLog__c WHERE source__c = :myEmail]
Not to mention that parameter binding instead of string concatenation means no need to worry about SQL injections etc.. Please consider getting used to these queries in brackets, they look weird in beginnign but will save your butt many times (mistyped field names etc).
As for actual concatenation - it works like you described it, I'm just unsure about the need to escape apostrophes. Binding the variables is safest way to go.
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dynamic_soql.htm
http://www.salesforce.com/us/developer/docs/api/index_Left.htm#CSHID=sforce_api_calls_soql.htm|StartTopic=Content%2Fsforce_api_calls_soql.htm|SkinName=webhelp

Is this sufficient to prevent query injection while using SQL Server?

I have recently taken on a project in which I need to integrate with PHP/SQL Server. I am looking for the quickest and easiest function to prevent SQL injection on SQL Server as I prefer MySQL and do not anticipate many more SQL Server related projects.
Is this function sufficient?
$someVal = mssql_escape($_POST['someVal']);
$query = "INSERT INTO tblName SET field = $someVal";
mssql_execute($query);
function mssql_escape($str) {
return str_replace("'", "''", $str);
}
If not, what additional steps should I take?
EDIT:
I am running on a Linux server - sqlsrv_query() only works if your hosting environment is windows
The best option: do not use SQL statements that get concatenated together - use parametrized queries.
E.g. do not create something like
string stmt = "INSERT INTO dbo.MyTable(field1,field2) VALUES(" + value1 + ", " + value2 + ")"
or something like that and then try to "sanitize" it by replacing single quotes or something - you'll never catch everything, someone will always find a way around your "safe guarding".
Instead, use:
string stmt = "INSERT INTO dbo.MyTable(field1,field2) VALUES(#value1, #value2)";
and then set the parameter values before executing this INSERT statement. This is really the only reliable way to avoid SQL injection - use it!
UPDATE: how to use parametrized queries from PHP - I found something here - does that help at all?
$tsql = "INSERT INTO DateTimeTable (myDate, myTime,
myDateTimeOffset, myDatetime2)
VALUES (?, ?, ?, ?)";
$params = array(
date("Y-m-d"), // Current date in Y-m-d format.
"15:30:41.987", // Time as a string.
date("c"), // Current date in ISO 8601 format.
date("Y-m-d H:i:s.u") // Current date and time.
);
$stmt = sqlsrv_query($conn, $tsql, $params);
So it seems you can't use "named" parameters like #value1, #value2, but instead you just use question marks ? for each parameter, and you basically just create a parameter array which you then pass into the query.
This article Accessing SQL Server Databases with PHP might also help - it has a similar sample of how to insert data using the parametrized queries.
UPDATE: after you've revealed that you're on Linux, this approach doesn't work anymore. Instead, you need to use an alternate library in PHP to call a database - something like PDO.
PDO should work both on any *nix type operating system, and against all sorts of databases, including SQL Server, and it supports parametrized queries, too:
$db = new PDO('your-connection-string-here');
$stmt = $db->prepare("SELECT priv FROM testUsers WHERE username=:username AND password=:password");
$stmt->bindParam(':username', $user);
$stmt->bindParam(':password', $pass);
$stmt->execute();
No, it's not sufficient. To my knowledge, string replacement can never really be sufficient in general (on any platform).
To prevent SQL injection, all queries need to be parameterized - either as parameterized queries or as stored procedures with parameters.
In these cases, the database calling library (i.e. ADO.NET and SQL Command) sends the parameters separately from the query and the server applies them, which eliminates the ability for the actual SQL to be altered in any way. This has numerous benefits besides injection, which include code page issues and date conversion issues - for that matter any conversions to string can be problematic if the server does not expect them done the way the client does them.
I partially disagree with other posters. If you run all your parameters through a function that double the quotes, this should prevent any possible injection attack. Actually in practice the more frequent problem is not deliberate sabotague but queries that break because a value legitimately includes a single quote, like a customer named "O'Hara" or a comment field of "Don't call Sally before 9:00". Anyway, I do escapes like this all the time and have never had a problem.
One caveat: On some database engines, there could be other dangerous characters besides a single quote. The only example I know is Postgres, where the backslash is magic. In this case your escape function must also double backslashes. Check the documentation.
I have nothing against using prepared statements, and for simple cases, where the only thing that changes is the value of the parameter, they are an excellent solution. But I routinely find that I have to build queries in pieces based on conditions in the program, like if parameter X is not null then not only do I need to add it to the where clause but I also need an additional join to get to the value I really need to test. Prepared statements can't handle this. You could, of course, build the SQL in pieces, turn it into a prepared statement, and then supply the parameters. But this is just a pain for no clear gain.
These days I mostly code in Java that allows functions to be overloaded, that is, have multiple implementations depending on the type of the passed in parameter. So I routine write a set of functions that I normally name simply "q" for "quote", that return the given type, suitably quoted. For strings, it doubles any quote marks, then slaps quote marks around the whole thing. For integers it just returns the string representation of the integer. For dates it converts to the JDBC (Java SQL) standard date format, which the driver is then supposed to convert to whatever is needed for the specific database being used. Etc. (On my current project I even included array as a passed in type, which I convert to a format suitable for use in an IN clause.) Then every time I want to include a field in a SQL statement, I just write "q(x)". As this is slapping quotes on when necessary, I don't need the extra string manipulation to put on quotes, so it's probably just as easy as not doing the escape.
For example, vulnerable way:
String myquery="select name from customer where customercode='"+custcode+"'";
Safe way:
String myquery="select name from customer where customercode="+q(custcode);
The right way is not particularly more to type than the wrong way, so it's easy to get in a good habit.
String replacement to escape quotes IS sufficient to prevent SQL injection attack vectors.
This only applies to SQL Server when QUOTED_IDENTIFIER is ON, and when you don't do something stoopid to your escaped string, such as truncating it or translating your Unicode string to an 8-bit string after escaping. In particular, you need to make sure QUOTED_IDENTIFIER is set to ON. Usually that's the default, but it may depend on the library you are using in PHP to access MSSQL.
Parameterization is a best practice, but there is nothing inherently insecure about escaping quotes to prevent SQL injection, with due care.
The rel issue with escaping strings is not the efficacy of the replacement, it is the potential for forgetting to do the replacement every time.
That said, your code escapes the value, but does not wrap the value in quotes. You need something like this instead:
function mssql_escape($str) {
return "N'" + str_replace("'", "''", $str) + "'";
}
The N above allows you to pass higher Unicode characters. If that's not a concern (i.e., your text fields are varchar rather than nvarchar), you can remove the N.
Now, if you do this, there are some caveats:
You need to make DAMNED SURE you call mssql_escape for every string value. And therein lies the rub.
Dates and GUID values also need escaping in the same manner.
You should validate numeric values, or at least escape them as well using the same function (MSSQL will cast the string to the appropriate numeric type).
Again, like others have said, parameterized queries are safer--not because escaping quotes doesn't work (it does except as noted above), but because it's easier to visually make sure you didn't forget to escape something.

Resources