Get all or part result from sql using one TSQL commnd - c#

Here is my condition.
There is a Text box in a form, if you don't input any thing, it would return all rows in this table. If you input something, it would return rows whose Col1 matches the input. I try to use the sql below to do it. But there is one problem, these columns allows Null value. It wouldn't return the row with NULL value. Is there any way to return all or matched row based on the input?
Update
I use the ObjectDataSource and ControlParameter to pass the parameter, when the input of control is empty, the ObjectDataSource would pass a DBNULL to the TSQL commnd.
Col1 Col2 Col3
ABCD EDFR NULL
NULL YUYY TTTT
NULL KKKK DDDD
select * from TABLE where Col1 like Coalesce('%'+#Col1Val+'%',[Col1])

Have you tried
SELECT *
FROM TABLE
WHERE COALESCE(Col1, '') LIKE COALESCE ('%'+#Col1Val+'%', [Col1])

Something like this might work.
select * from TABLE where Coalesce(Col1,'xxx') like Coalesce('%'+#Col1Val+'%',Col1, 'xxx')

SELECT * FROM [TABLE]
WHERE (Col1 LIKE '%'+#Col1Val+'%' OR (#Col1Val = '' AND Col1 IS NULL))

Use this:
SELECT *
FROM TABLE
WHERE
( #Col1Value IS NOT NULL AND COALESCE(Col1, '') LIKE '%' + #Col1Val +'%' )
OR #Col1Value IS NULL
Or perhaps use this, so null won't creep in to your query:
string nullFilteredOutFromQueryString = #"SELECT *
FROM TABLE
WHERE
( #Col1Value <> '' AND COALESCE(Col1, '') LIKE '%' + #Col1Val +'%' )
OR #Col1Value = ''";
var da = new SqlDataAdapater(nullFilteredOutFromQueryString, c);
// add the TextBox's Text property directly to parameter's value.
// this way, null won't creep in to your query
da.SelectCommand.Parameters.AddWithValue("Col1Value", txtBox1.Text);
da.Fill(ds, "tbl");

Related

(pass "all" in parameter ?) | how can I make parameter ? in WHERE filter to be a return of ALL in sql request

I am making a wpf C# app following MVVM.
It processes data from accdb (with several connected tables) using DataSet via ServerExplorer.
I am trying to make a filtered search right now.
SELECT IDBug, [Date], ReportedBy, Replicated, ReproducableSteps, AppArea, Status, FixedVer, FixedBy, Notes, Title
FROM Bugs
WHERE ([Date] >= ?)
AND ([Date] <= ?)
AND (Status = ?)
AND (AppArea = ?)
AND (Replicated = ?)
AND (ReportedBy = ?)
This was working, but only if use all the filter settings.
int idAr = (from DataRow dr in ars.GetData().Rows
where (string)dr["Area"] == AreaSe.ToString()
select (int)dr["IDArea"]).FirstOrDefault();
int idCust = (from DataRow dr in custs.GetData().Rows
where (string)dr["CustomerName"] == CustomS.ToString()
select (int)dr["IDCustomer"]).FirstOrDefault();
BugTable = bugs.GetT(StartDate, StopDate, State, idAr, replicationS, idCust);
I do have some null values in my data, that is why I tried to do smth similar to
WHERE Title = ? OR (? IS NULL))
instead of
WHERE Title = ?
for each of the parameters. But it messes up the data types...
I don`t think that is smart to write a different sql query for each case, so I need to know how cann I pass "SELECT ALL" to a ? parameter.
You can do use case in where clause like this. You can pass null as default value for the parameter.
So it will return the records for #param if it is not passed else it will return all records.
SELECT Col1, Col2….
FROM TableName
WHERE ColName = CASE WHEN #param IS NULL THEN ColName ELSE #param END

SQL Server Show Results when Record not found

I am trying to get SQL to list not found when a machine name lookup is not in the database. I have the query working but I need to integrate it into C# where I have other queries. As it stands it is a lot more convoluted than I want it to be, I am guessing there is a much more intelligent and concise why of having the SQL achieve the same result.
DECLARE #myHostCount as INT
DECLARE #myHostName1 as Varchar(50);
DECLARE #myHostName2 as Varchar(50) = 'Machine220054';
DECLARE #myHostCount1 as INT
DECLARE #myHostName3 as Varchar(50);
DECLARE #myHostName4 as Varchar(50) = 'Machine22054';
SET #myHostCount1 = (SELECT COUNT(*) FROM db_owner.host WHERE name LIKE '%Machine22054%')
SET #myHostName3 = (SELECT Name FROM db_owner.host WHERE name LIKE '%Machine22054%')
SET #myHostCount = (SELECT COUNT(*) FROM db_owner.host WHERE name LIKE '%Machine220054%')
SET #myHostName1 = (SELECT Name FROM db_owner.host WHERE name LIKE '%Machine220054%')
SELECT
CASE
WHEN #myHostCount = 1 THEN 'Found'
WHEN #myHostCount = 0 THEN 'Not Found'
END AS 'Result',
#myHostName2 AS 'HostName'
UNION
SELECT
CASE
WHEN #myHostCount1 = 1 THEN 'Found'
WHEN #myHostCount1 = 0 THEN 'Not Found'
END AS 'Result',
#myHostName4 AS 'HostName'
Output:
Result Machine Name
--------------------------
Found Machine220054
Not Found Machine22054
You can try this:
DECLARE #myHostName2 as Varchar(50) = 'Machine220054';
DECLARE #myHostName4 as Varchar(50) = 'Machine22054';
DECLARE #hostName TABLE (
Name VARCHAR(255)
);
INSERT INTO #hostName (Name)
VALUES (#myHostName2), (#myHostName4)
SELECT HostName = HostName.name,
Result = IIF(COUNT(*) = 0, 'Not Found', 'Found')
FROM #hostName AS HostName
LEFT JOIN db_owner.host ON host.name LIKE '%' + HostName.Name + '%'
GROUP BY HostName.name;
First: Try to remove as much procedural logic in SQL as possible.
Second: Try to minimize the use of "Like" queries if at all possible. It will hinder indexing and cause bottlenecks eventually, or, at least limit it to ending with a "%" instead of starting it with one.
Third: you are assuming that there will only be zero or one hit in your code. What if (given either non-unique or like based queries) there are more than one?
I'd go for something like this:
declare #looking table (name varchar(50))
insert into #looking (name) values ('Machine220054'),('Machine22054')
select case when t.name is null then 'Not Found' else 'Found' end as [FoundOrNot], t.name as [FoundName],l.name as [SearchName]
from #looking as l
left outer join db_owner.host as t
on t.name like '%' + l.name + '%'
UPDATE: Tested against a random table, removed "group by" on account of either one or no hit expected.
Just to provide an update, I ended up taking the results from the DR reader and entering them into a datatable, since the dr reader can only be read once. Then I compared the selections from the listbox with the contents from the datatable then added the difference to another datatable then displayed the results in a datagrid, this produced the desired outcome of results found, being listed and the objects not found being listed as not found.

How to add data into a table only if it doesnt already exist?

I have thought about using distinct but im not too sure how to do it as a single query for efficiency of code, is there a way? I am basically trying to check if there is already an existing data entry, I am trying to check it with BookingTime. Thanks :)
This is my SQL query:
string bookingInfo = "INSERT INTO Booking(BookingDate, BookingTime, CustomerID, EmployeeID, ServiceType, BookingLength) " +
"VALUES (#BookingDate, #BookingTime, #CustomerID, #EmployeeID, #ServiceType, #BookingLength) " +
"where not exists (SELECT 1 FROM Booking WHERE BookingTime = #BookingTime)";
The error I receive: "Additional information: Query input must contain at least one table or query."
The best way is to let the database do the checking.
Create a unique index or constraint on the table:
create unique index unq_booking_bookingtime on booking(bookingtime);
Note: this is based on your query. It seems unlikely to me that only bookingtime defines uniqueness.
The database will then generate an error if it encounters duplicates. You can prevent the error using insert ignore or insert on duplicate key update (the latter is the preferred method).
The WHERE clause is invalid is invalid in the "INSERT ... VALUES" statement shown.
MySQL does provide an "INSERT ... SELECT ..." form of the INSERT statement (which does not use a VALUES clause). The SELECT statement can have a WHERE clause, but to include a WHERE clause in a SELECT, there has to be a FROM clause. You can use an inline view (aka a derived table) to return a single row, or you could use the builtin Oracle-style dummy table DUAL to return a single row. (We don't care what columns get returned, we just need one row returned.)
For example:
INSERT INTO Booking
( BookingDate
, BookingTime
, CustomerID
, EmployeeID
, ServiceType
, BookingLength
)
SELECT #BookingDate
, #BookingTime
, #CustomerID
, #EmployeeID
, #ServiceType
, #BookingLength
FROM ( SELECT 1 ) i
WHERE NOT EXISTS
( SELECT 1
FROM Booking b
WHERE b.BookingTime = #BookingTime
)
Now the SELECT statement (which can be tested separately from the INSERT) will return either zero or one rows. And whatever row it returns will be passed to the INSERT.
As an alternative to the "NOT EXISTS" predicate, you could use an anti-join pattern:
SELECT #BookingDate
, #BookingTime
, #CustomerID
, #EmployeeID
, #ServiceType
, #BookingLength
FROM ( SELECT 1 ) i
LEFT
JOIN Booking b
ON b.BookingTime = #BookingTime
WHERE b.BookingTime IS NULL
string bookingInfo = "INSERT INTO Booking(BookingDate, BookingTime, CustomerID, EmployeeID, ServiceType, BookingLength) " +
"SELECT #BookingDate, #BookingTime, #CustomerID, #EmployeeID, #ServiceType, #BookingLength " +
" FROM Booking WHERE NOT EXISTS (SELECT * FROM Booking WHERE BookingTime = #BookingTime) LIMIT 1 "
Try this SqlFiddle

C# DataTable.Select() - How do I format the filter criteria to include null?

This doesn't work
DataTable myNewTable = myDataTable.Select("Name <> 'n/a'").CopyToDataTable();
myDataTable has a row named Name. I would like to select the rows from this table where Name is not equal to "n/a". It selects but still am missing the null values i need the null values too.
Can anyone help?
Try this
myDataTable.Select("[Name] is NULL OR [Name] <> 'n/a'" )
Edit: Relevant sources:
DataTable.Select Method (String)
Expression filtering syntax
Try out Following:
DataRow rows = DataTable.Select("[Name]<>'n/a'")
For Null check in This:
DataRow rows = DataTable.Select("[Name] <> 'n/a' OR [Name] is NULL" )
The way to check for null is to check for it:
DataRow[] myResultSet = myDataTable.Select("[COLUMN NAME] is null");
You can use and and or in the Select statement.
try this:
var result = from r in myDataTable.AsEnumerable()
where r.Field<string>("Name") != "n/a" &&
r.Field<string>("Name") != "" select r;
DataTable dtResult = result.CopyToDataTable();

Using if exists

I'm having an issue with duplicates being inserted on refresh. Our team here decided using 'if exists' in sql is the best way to stop duplicate inserts. However, what if a parameter is set to null?
string cmdText = " if (not exists(select * from table where field1 = #field1 and field2 = #field2 and field3 = #field3)) Insert into table(field1,field2,field3) Values(#field1,#field2,#field3)";
if (txtfield1.text != "")
cmd.Parameters.Add(new SqlParameter("#field1", txtfield1.text));
else
cmd.Parameters.Add(new SqlParameter("# field1", DBNull.Value));
cmd.Parameters.Add(new SqlParameter("#field2", txtfield2));
cmd.Parameters.Add(new SqlParameter("#field3", txtfield3));
This does not work when there is a null value in field1.
You could wrap your fields around isnull's or something to take into account for the nulls
isnull(field1, '') = isnull(#field1, '') and
isnull(field2, '') = isnull(#field2, '') and
isnull(field3, '') = isnull(#field, '')
Would it not be a better idea to reduce the load on the database and attack the problem at the source?
Usually this kind of error occurs when you have a page that handles its own submission, ie the form action property points back to itself, so when someone hits refresh after they posted something, the POST data is still 'live' and gets posted back to the page.
A better way is to have the data submitted to a second object which deals with insertion and then redirects back to where it came from, the redirection clears the POST data and you save yourself a LOT of unnecessary queries.
Just my 2c
where field1 IS #field1
is not valid syntax
Use isnull()
So:
string cmdText = " if (not exists(select * from table where isnull(field1, '') = isnull(#field1, '') ...
If you don't want duplicates in your table, maybe your table should have a primary key or at least a unique clustered index on your field1, field2 and field3.
That way, you could just try ton insert and catch the error if the row already exists.
following condition will help.
field1 is null or #field1 = field1
In field definition you can use NOT NULL constraint so that null element's wouldn't be able to be there.
http://www.w3schools.com/SQl/sql_notnull.asp
And use sql UNIQUE constraint so they have to be unique.
http://www.w3schools.com/SQl/sql_unique.asp
CREATE TABLE YourTable
(
Field1 varchar(255),
Field2 varchar(255),
Field3 varchar(255),
CONSTRAINT uc_fields UNIQUE (Field1, Field2, Field3)
)
CREATE TRIGGER table_null_convert
ON YourTable
FOR INSERT, UPDATE
REFERENCING NEW ROW AS n
FOR EACH ROW
SET n.Field1 = ISNULL(n.Field1, '')
SET n.Field2 = ISNULL(n.Field2, '')
SET n.Field3 = ISNULL(n.Field3, '');
And you'll be allowed to insert if these conditions are met.
Hope I got the trigger right. :)
Well you would have to use IS instead of = if you are going to set #field1 to NULL. NULL is not gonig to work with the equality operator. You need to use an equivalence type 'IS' for that.
string cmdText = " if (not exists(select * from table where field1 = #field1 and field2 = #field2 and field3 = #field3)) Insert into table(field1,field2,field3) Values(#field1,#field2,#field3)";
goes to
string cmdText = "";
if (txtfield1.text != "")
cmdText = " if (not exists(select * from table where field1 = #field1 and field2 = #field2 and field3 = #field3)) Insert into table(field1,field2,field3) Values(#field1,#field2,#field3)";
else
cmdText = " if (not exists(select * from table where field1 IS #field1 and field2 = #field2 and field3 = #field3)) Insert into table(field1,field2,field3) Values(#field1,#field2,#field3)";
end if
Rinse and repeat and refactor :)

Categories

Resources