Dynamically sql query to select top (n) elements [duplicate] - c#

This question already has answers here:
How to replace text in string in C#?
(2 answers)
Closed 8 years ago.
SELECT TOP 100 * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC
I want to replace find 'TOP 100' string and replace it with 'TOP 200' or any other value.
Can you please let me know how to do it in C#?

if you are writing query in your c# code you can use:
int topCount=1000;
string query= "SELECT TOP ("+i.toString()+") * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC"
But if you want to send parameter to your SP then you can use:
Declare #i int=1000;
SELECT TOP (#i) * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC

It sounds to me as if you simply want to replace part of the string with another, so like:
string sql = "SELECT TOP 100 * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC";
sql = sql.Replace("TOP 100", "TOP 200");
If the number is dynamic and you want to replace it with a different one you could use regex:
string sql = "SELECT TOP 100 * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC";
string pattern = #"\bTOP\b *(\d+)";
sql = Regex.Replace(sql, pattern, m => "TOP 200");

DECLARE #topval int=100
SELECT TOP #topval * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC

you want to use string replace function.string replace function

If you are not using stored procedures, you can concatenate the limit in the command text in C#:
int toplimit = 200;
cmd.CommandText="SELECT TOP " + toplimit.ToString() + " * FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC";

I think it should be as simple as this
private string GetSql(int maxRecords)
{
string statement = "SELECT TOP " + maxRecords + " FROM DSMS_Log.dbo.LoggingDetail WITH(NOLOCK) ORDER BY LogTime DESC ";
return statement;
}
you can also modify the parameters and change your SQL query.

I'd use regex for that. Because i think its the best way to get all variations in one statement.
string oldString = "Select top 500 from wherever";
string newLimit = "top 20";
string result = System.Text.RegularExpressions.Regex.Replace(oldString , "TOP (\\d)+",newLimit , System.Text.RegularExpressions.RegexOptions.IgnoreCase );
So put in your old string, replace any "TOP x" string with another version given as newLimit in my Example.

For C# solution you will do better using a parameter instead of string manipulation.
simply like this:
int count = 200;
var sql = string.Format("SELECT TOP {0} FROM [Rest_Of_Your_Query]", count);
if you will use a parameter it will be easier for you to know when to change (in case you want to replace only when the value is 100) and to which value (200, 300 whatever).
For SQL solution take a look at the answer from #Ganesh_Devlekar

Related

How to add column in SELECT statement dynamically in tSQL based on condition?

I am creating a tSql with parameters and based on some condition I want to add column in SELECT statement and I am not sure how to do it.
My Logic:
var keywordClause = keyword.IsNotEmpty()
? "[Name] like '%" + keyword + "%'"
: "1 = 1";
// keywordClause = "[Name] like '%Test%'"
var orderBy = sortParameters.ToOrderBy();
// orderBy = "Name ASC"
var parameters = new List<SqlParameter>
{
new SqlParameter("#Keyword", keywordClause),
new SqlParameter("#OrderBy", orderBy)
};
var sql = string.Format(#"SELECT Id,
Name,
CreateDateTime Created
FROM CallCenter WITH (NOLOCK)
WHERE(IsDeleted = 0)
AND #Keyword
ORDER BY #OrderBy");
return _PageList(ctx => ctx.CallCenterSummaries.SqlQuery(sql, parameters.ToArray())
.AsQueryable()
.Select(d => d.TrimSpaces()), page, pageSize);
Based on my logic, I am expecting this query:
SELECT Id,
Name,
CreateDateTime Created
FROM CallCenter WITH (NOLOCK)
WHERE(IsDeleted = 0)
AND [Name] like '%Test%'
ORDER BY Name ASC;
Here I am getting "An expression of non-boolean type specified in a context where a condition is expected, near 'ORDER'." exception and I believe it is taking Name as a string. How can I get desired results?
You can't have SqlParameter as an entire clause - it needs to be right hand side of the clause. For your scenario - the below should work.
var parameters = new List<SqlParameter>
{
new SqlParameter("#Keyword", keyword.IsNotEmpty() ? keyword : "%")
};
var sql = string.Format($#"SELECT Id,
Name,
CreateDateTime Created
FROM CallCenter WITH (NOLOCK)
WHERE(IsDeleted = 0)
AND [Name] like #Keyword
ORDER BY {orderBy}");
EDIT:
I've edited my code sample to use order by as a value in the interpolated string rather than as a SqlParameter, however, this does open you up to a Sql injection if the value of the orderBy is influenced by user's inputs.
Alternatively, I would recommend not using ORDER BY clause at all in your query and sorting results in memory before passing them back for display.

SQL - Syntax Error When Trying to Increment a Value

I'm using SQL Server in a C# project for a troubleshooting program and I have a table that contains ID,Question,QuestionId,Solution and Rank. I previously asked a question and it worked for selecting, so I tried modifying that for an Update instead. I'm trying to increment the rank of the solution with the highest rank by 1.
sql = "UPDATE dbo.Questions SET Rank = Rank + 1 q WHERE Rank=(SELECT MAX(Rank) FROM dbo.Questions i where i.QuestionId = q.QuestionId) AND q.QuestionId = " + questionId;
I get the following error with this:
Incorrect syntax near 'q'
Incorrect syntax near the keyword 'AND'
The table alias is in the wrong place. In SQL Server, you want a FROM clause:
UPDATE q
SET Rank = Rank + 1
FROM dbo.Questions q
WHERE Rank = (SELECT MAX(Rank)
FROM dbo.Questions i
WHERE i.QuestionId = q.QuestionId
) AND
q.QuestionId = " + questionId;
You can also write this as:
UPDATE q
SET Rank = Rank + 1
FROM (SELECT TOP (1) q.*
FROM dbo.Questions q
WHERE q.QuestionId = " + questionId
ORDER BY rank DESC
);
This makes it obvious that you only want to update one row.
Let me also add . . . learn to use query parameters. Don't put questionId directly into the query string. That is just a way to introduce syntax errors that are really hard to debug.

Executing query with like is not working

I have this code:
string query = "SELECT * FROM dbo.customer WHERE mobileNumber Like '%#mobileNumber'";
When I execute that code from c#, I got empty results
However when I execute this query in my sql managmenet studio
SELECT * FROM dbo.customer WHERE mobileNumber Like '%454545'
I got result.
What I am missing?
Try this:
string query = "SELECT * FROM dbo.customer WHERE mobileNumber Like '%' + #mobileNumber
This is assuming #mobileNumber is a parameter containing the value for which you want to search.
It seems from your code that #mobileNumber is a parameter. Yet, you place it here as a string.
Try putting the % in a string and the parameter separately unquoted:
string query = "SELECT * FROM dbo.customer WHERE mobileNumber Like '%' + #mobileNumber";

i need to use SELECT statment with UNION ALL several times (unknown no' times)

i need to use SELECT statment with UNION ALL several times (unknown nomber times).
I did it with c# ! can i do it inside a stored procedure ?
c#
// this code selects a number of users thoughts. for every user it is getting only 6 thoughts
// according to each user page number (friendsToughtPageNum).
for (int i = startUser-1; i < endUser; i++){
subSql += "SELECT * FROM (SELECT TOP " + 6 * friendsToughtPageNum[i] + " * FROM (SELECT TOP thought, firstName, lastName FROM tbl_thoughts INNER JOIN tbl_users ON thoughtUserID = userID WHERE userID=" + IDs[i] + " ORDER BY thoughtID ASC) AS T" + i + " ORDER BY thoughtID DESC) AS TA" + i + " UNION ALL ";
}
subSql = subSql.Remove(subSql.Length - 11, 11);
sql = subSql;
Yes, you can do it in a stored procedure by using a CURSOR and looping that way. You can then save the results to either a temp table and read from that or you can continue to use UNION ALL

Retrieving distinct record using join in SQL

I am running a sql query using two tables namely QuestionInsert and Question_Papers.
The columns in th erespective table are as follows:-
Table:-QuestionInsert
Columns:-QuestionNum,Question,Answer,CatId,SubCatId
Table:-Question_Papers
Columns:-QuestionNum
I want an sql query which will retrieve all QuestionNum,Question,Answer from table QuestionInsert which QuestionNum is present in table Question_Papers.
Also, I want to retrieve all QuestionNum,Question,Answer from table QuestionInsert which QuestionNum is not present in table Question_Papers.
This data is displayed on a Grid View.The queries I am using are as follows:-
The Query for first condition is:
SELECT F.QuestionNum,
F.Question,
F.Answer
FROM QuestionInsert F
INNER JOIN Question_Papers FS ON F.[QuestionNum]=FS.QuestionNum
WHERE ((F.QuestionNum=FS.QuestionNum) AND (F.CatId='" +
DropDownList1.SelectedValue + "' And F.SubCatId='" + DropDownList3.SelectedValue + "'))
ORDER BY F.QuestionNum DESC;
The other query for 2nd condition. is:-
SELECT F.QuestionNum,
F.Question,
F.Answer
FROM QuestionInsert F INNER JOIN Question_Papers FS ON F.[QuestionNum]!=FS.QuestionNum
WHERE ((F.QuestionNum!=FS.QuestionNum) AND (F.CatId='" + DropDownList1.SelectedValue + "'
And F.SubCatId='" + DropDownList3.SelectedValue + "'))
ORDER BY F.QuestionNum DESC
My code is retrieving correct information but if more than one row of same QuestionNum is present in Question_Papers table, it is displaying all the rows repeatedly. I want to display the unique rows which are present and not present in table Question_Papers separately.
Kindly help me.
You could try the following for the second condition:
SELECT F.QuestionNum,F.Question,F.Answer
FROM QuestionInsert F
WHERE (F.CatId='" + DropDownList1.SelectedValue + "' And F.SubCatId='" + DropDownList3.SelectedValue + "')
AND F.QuestionNum NOT IN (SELECT QuestionNum FROM Question_Papers)
ORDER BY F.QuestionNum DESC
And this for the first condition:
SELECT F.QuestionNum,F.Question,F.Answer
FROM QuestionInsert F
WHERE (F.CatId='" + DropDownList1.SelectedValue + "'
AND F.SubCatId='" + DropDownList3.SelectedValue + "')
AND F.QuestionNum IN (SELECT QuestionNum FROM Question_Papers)
ORDER BY F.QuestionNum DESC";
However, there are serious problems with your code - have you looked into SQL injection? There are many data access frameworks, like Entity Framework, that would push you down a better route.
Your first query can be rewritten using EXISTS
SELECT F.QuestionNum,F.Question,F.Answer FROM QuestionInsert F
WHERE EXISTS (SELECT * FROM Question_Papers P WHERE P.QuestionNum = F.QuestionNum)
AND F.CatId='" + DropDownList1.SelectedValue + "'
AND F.SubCatId='" + DropDownList3.SelectedValue + "'
Second query using NOT EXISTS
SELECT F.QuestionNum,F.Question,F.Answer FROM QuestionInsert F
WHERE NOT EXISTS (SELECT * FROM Question_Papers P WHERE P.QuestionNum = F.QuestionNum)
AND F.CatId='" + DropDownList1.SelectedValue + "'
AND F.SubCatId='" + DropDownList3.SelectedValue + "'
Please note that with the way those queries are written (which was taken from your question), you are vulnerable to SQL Injection. You should use parameters instead.
There doesn't appear to be a need to use a join nor a reason for repeating the join clause within where. Form what I can gather all you need to do is check for existence, which recent versions (2005+) of sql server supports with EXISTS. Doing this as a single query than a correlated subquery can be used to check and flag existence
DECLARE #question_insert TABLE ( id INT, question VARCHAR(50), answer VARCHAR(50), catid INT, subcatid INT )
DECLARE #question_paper TABLE ( id INT, question_insert_id INT )
INSERT INTO #question_insert ( id, question, answer, catid, subcatid )
VALUES
(1, 'How old are you?', '20', 1, 1),
(2, 'Who was the first president?', '?', 2, 1)
INSERT INTO #question_paper ( id, question_insert_id )
VALUES (1, 1),(2, 1)
SELECT
qi.id,
qi.question,
qi.answer,
CASE WHEN EXISTS(SELECT 1 FROM #question_paper qp
WHERE qp.question_insert_id = qi.id)
THEN 'Yes' ELSE 'No' END AS in_question_paper
FROM #question_insert qi
--WHERE qi.catid=#catid AND qi.subcatid=#subcatid
demo
Alternatively AS individual queries
SELECT
qi.id,
qi.question,
qi.answer,
'Yes' AS in_question_paper
FROM #question_insert qi
WHERE EXISTS(SELECT 1 FROM #question_paper qp
WHERE qp.question_insert_id = qi.id)
And
SELECT
qi.id,
qi.question,
qi.answer,
'No' AS in_question_paper
FROM #question_insert qi
WHERE NOT EXISTS(SELECT 1 FROM #question_paper qp
WHERE qp.question_insert_id = qi.id)
I will reiterate that you should read up on SQL Injection and not concatenate user input into queries.
Also re. DISTINCT not being "acceptable in joins" that is not the case. What is not acceptable is to use DISTINCT and refer to a column that is not part of select list in another part of the query (in this case it would've been the WHERE clause), a way round this is to use GROUP BY instead.

Categories