How to pass absolute database name,server name as parameter? - c#

I have a requirement where I need to select data from database DB1 and insert into database DB2.
update [Server1\SQLEXPRESS].[DB1].dbo.table1
set CName = (select CName
from [Server2\SQLEXPRESS].[DB2].dbo.table1
where CID = 3)
So above script is working fine.
Now I want to pass
[Server1\SQLEXPRESS].[DB1]
[Server2\SQLEXPRESS].[DB2]
as parameters, because the server name and database can be different in real time environment.
Can you tell me how to achieve below goal?
create procedure
#CID numeric,
#ServerName1 serverDataType,
#ServerName2 serverDataType,
#DBName1 dbDataType,
#DbName2 dbDataType
as
update #ServerName1.#DBName1.dbo.table1
set CName = (select CName
from #ServerName2.#DBName2.dbo.table1
where CID = #CID)

Try this something in this fashion:
DECLARE #ServerName1 varchar(max) = 'MyServer'
DECLARE #DB1 varchar(max) = 'MyDB'
EXEC('update ' + #ServerName1 + '.' + DB1 + '.dbo.table1
set CName= (select CName from ' + #ServerName1 + '.' + DB1 +
'.dbo.table1' where CID ='+ #CID)

Related

How to search grid view using registered date column using sql query

How to search grid view using date column?
In a SQL Server database, I have a table Priority with 3 columns id, name and registered date. For registered date, default value is getdate() which automatically generates the record created date and time. Now in grid view, I want to search records using this registered date.In grid view, I have dropdown search by using name and date.
CREATE PROCEDURE [dbo].[SEARCHPRIOR]
#SearchBy VARCHAR(50),
#SearchVal VARCHAR(50),
AS
BEGIN
IF #SearchBy = '1'
BEGIN
SELECT *
FROM PRIORITY
WHERE P_NAME LIKE '%' + #SearchVal + '%'
END
ELSE IF #SearchBy = '2'
BEGIN
SELECT *
FROM PRIORITY
WHERE P_TS LIKE '%' + #SearchVal + '%'
END
ELSE
BEGIN
SELECT * FROM PRIORITY
END
END
I have tried searching with this query but getting no results found in grid view. This is how table look like in SQL Server:
P_ID P_NAME P_TS
-------------------------------------------
1 High 2019-04-23 16:17:08.097
2 Medium 2019-04-24 16:17:23.070
3 Low 2019-04-25 16:17:32.420
This is how I call the stored procedure, with name it is searching correctly but with date, it is showing no results found.
public DataTable searchPRIOR(string searchBy, string searchVal)
{
SqlCommand cmd = new SqlCommand("SEARCHPRIOR", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#SearchBy", searchBy);
cmd.Parameters.AddWithValue("#SearchVal", searchVal);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
Your stored procedure will not compile because of a dangling comma.
Your WHERE conditions cannot use an index, so there is no reason to split this across multiple queries.
You might consider writing the logic as:
CREATE PROC [dbo].[SEARCHPRIOR] (
#SearchBy varchar(50),
#SearchVal varchar(50)
) AS
BEGIN
SELECT P.*
FROM PRIORITY P
WHERE (#SearchBy = '1' AND P_NAME like '%' + #SearchVal + '%') OR
(#SearchBy = '2' AND P_TS like '%' + #SearchVal + '%') OR
(COALESCE(#SearchBy, '') NOT IN ('1', '2'));
END;
I don't know if simplifying the code will fix your problem. It is likely to be an issue in how the SP is being called, not defined.

Insert from One MS Access database to Another MS Access database

I have to take the data from MS Access DB to another.
This was insert statement used
cmd.CommandText = #"Insert Into [MS Access;PWD=pw;DATABASE=" + currentDBPath + #"].[Orders] Select * FROM [Orders] where OrderDate>=#" + from.ToShortDateString() + "# and OrderDate <=#" + to.ToShortDateString() + "# and IsCustomer=Yes ";
This statement works fine. But some one started to enter the data directly to target database and also in the source. This created duplicated records. Now I want to copy those orders from source which are not in the target DB's table.
Assuming Orders table has a primary key named IDOrers, you must bring both tables to one DB, so you can compare data.
Easy option: have in Sours DB a link to [Orders] on Destination DB, named OrdersDest. In that case you create on destination a query of missing orders, named MissingOrders :
SELECT Orders.* FROM Orders LEFT JOIN OrdersDest ON OrdersDest.IDOrders = Orders.IDOrders WHERE OrdersDest.IDOrders Is Null
Your Command will now look like this:
cmd.CommandText = #"Insert Into [MS Access;PWD=pw;DATABASE=" + currentDBPath + #"].[Orders] Select * FROM [MissingOrders] where OrderDate>=#" + from.ToShortDateString() + "# and OrderDate <=#" + to.ToShortDateString() + "# and IsCustomer=Yes ";
You could also pass the data through this linked table:
cmd.CommandText = #"Insert Into [OrdersDest] Select * FROM [MissingOrders] where OrderDate>=#" + from.ToShortDateString() + "# and OrderDate <=#" + to.ToShortDateString() + "# and IsCustomer=Yes ";
I didn't find any solution to what I was looking for in my question , So I decided to just delete the duplicated data in destination database.
I used the below statement to delete the data ,
Delete * from Orders where AutoOrderID in (SELECT Orders.AutoOrderID FROM Orders Inner JOIN OrdersSource ON OrdersSource .OrderId = Orders.OrderId and OrdersSource .OrderDate=Orders.OrderDate);

How to use IF EXISTS in SQL (ifexists update, else insert in SQL)

string searched = TextBox1.Text; // for example, text is 4477
...
sorgu.CommandText = "IF EXISTS(SELECT * FROM [Pins] WHERE Pin =' " + searched.ToString() + " ') BEGIN UPDATE [Pins] SET SAY= SAY+1, Pin = ' " + searched.ToString() + " ' END ELSE BEGIN INSERT INTO Pins(SAY,Pin) VALUES (+1,' " + searched.ToString() + " ') END";
...
I am using SAY for counting the number of searches.
This code is changing all records on column (Pins) to searched text.
Where/What is my fault?
In pseudo code, you're saying
IF EXISTS(SELECT Statement) UPDATE ALL ROWS
The correct way to do this with EXISTS is
UPDATE TABLE
WHERE EXISTS(Correlated SELECT Statement)
You need to have a where to not update all records. This would fix it.... but is a horrible query.
IF EXISTS(SELECT * FROM [Pins] WHERE Pin = 'searched.ToString()')
BEGIN
UPDATE [Pins] SET SAY = SAY + 1
WHERE [Pin] = 'searched.ToString() '
END
ELSE
BEGIN
INSERT INTO Pins(SAY, Pin) VALUES (1, 'searched.ToString()')
END
You missed the WHERE clause.
I would also prefer using Parameters instead of string concatenated query (which makes your code open to SQL injection attacks)
string searched = TextBox1.Text; // for example, text is 4477
sorgu.CommandText = "IF EXISTS(SELECT * FROM [Pins] WHERE Pin = #searched) BEGIN UPDATE [Pins] SET SAY=SAY+1 WHERE Pin = #searched END ELSE BEGIN INSERT INTO Pins(SAY,Pin) VALUES (1, #searched) END";
sorgu.Parameters.AddWithValue("#searched", TextBox1.Text);

LINQ not causing insert trigger

Me again with another LINQ question.
Our database is set up so that there is an event trigger when an SQL insert occurs.
Now, this trigger is not being called when I am using LINQ. Is there something in particular I need to do to make the database see the LINQ command as an insert? (Code below). I should say that the data is being entered into the database correctly, but the trigger is not happening.
Thanks in advance.
LINQ code:
private void SaveToWebsure()
{
using (MagTestDataContext context = new MagTestDataContext())
{
//create new instance of tblPolicy object
tblPolicy policy = new tblPolicy();
//generate PolicyID number
policyNo = context.ExecuteQuery<int>("DECLARE #ret INT; EXEC spNextPolicyID #ret OUTPUT; SELECT #ret").Single();
//add values to field
policy.PolicyID = policyNo;
policy.RecordType = "New Business";
policy.SchemeID = 17;
policy.Status = "Quote";
policy.Title = ddTitle.Text + ' ' + tbSurname.Text;
policy.PolicyHolder = ddTitle.Text + ' ' + tbFirstName.Text + ' ' + tbSurname.Text;
policy.SearchKey = tbSurname.Text;
policy.EMail = tbEmail.Text;
policy.Telephone = tbTelephone.Text;
policy.Address1 = tbAddressLine1.Text;
policy.Address2 = tbAddressLine2.Text;
policy.Address3 = tbAddressLine3.Text;
policy.Address4 = tbAddressLine4.Text;
policy.PostCode = tbPostcode.Text;
policy.rowguid = System.Guid.NewGuid();
policy.Comments = "Current/Previous Insurer: " + tbInsurer.Text + "; " + "Reason for refused insurance: " + ddReason.SelectedItem.Text + "; " + "Further reasons specified: " + tbOther.Text;
//insert new contact_detail object
context.tblPolicies.InsertOnSubmit(policy);
//submit changes to database
context.SubmitChanges();
}
STORED PROCEDURE:
ALTER PROCEDURE spNextPolicyID #PolicyID int output AS
begin tran
/* update tblIdNumbers set ApplicantId = ApplicantId
set #Policyid = (select ApplicantID from tblIdNumbers)
update tblIdNumbers set ApplicantId = ApplicantId + 1 */
set Rowcount 0
SET NOCOUNT ON
exec dbo.spNextIdNumber #PolicyID Output,'PolicyId'
commit tran
LINQ is not doing anything special in the background. A couple of things you should check
use SQL Profiler to see what query is being generated and what runs against the DB
check and see if the trigger is enabled just before the query runs
tip: if you're moving large amounts of data avoid triggers if you can (every case is different, just sayin) we usually disable/enable triggers from code when working with big data

Large SQL script calls every 5min that is crashing IIS pool?

Context:
I have a dozen of servers.
Each server have a IIS with a site that executes the following large SQL script every 5 minutes.
On some servers, the pool that hosts the site crash. The pool contains this site only.
I need to recycle the pool after each crash... with my hands currently.
So there is an issue with the site and, I think, with the large SQL script.
The C# code that calls the SQL script:
string root = AppDomain.CurrentDomain.BaseDirectory;
string script = File.ReadAllText(root + #"..\SGBD\select_user_from_all_bases.sql").Replace("$date", dtLastModif);
string connectionString = #"Data Source=(local);Integrated Security=SSPI";
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
var command = new SqlCommand(script, connection);
var reader = command.ExecuteReader();
var users = new List<UserModel>();
while (reader.Read())
{
users.Add(new UserModel()
{
dbName = String.Format("{0}", reader[0]),
idExternal = int.Parse(String.Format("{0}", reader[1])),
firstname = String.Format("{0}", reader[2]),
lastname = String.Format("{0}", reader[3]),
login = String.Format("{0}", reader[4]),
password = String.Format("{0}", reader[5]),
dtContractStart = reader[6] != DBNull.Value ? (DateTime?)reader[6] : null,
dtContractEnd = reader[7] != DBNull.Value ? (DateTime?)reader[7] : null,
emailPro = String.Format("{0}", reader[8]),
emailPerso = String.Format("{0}", reader[9])
});
}
return users;
}
And the SQL script:
USE master
DECLARE db_names CURSOR FOR
SELECT name FROM sysdatabases WHERE [name] LIKE 'FOO_%' AND [name] NOT LIKE 'FOO_TRAINING_%'
DECLARE #db_name NVARCHAR(100)
DECLARE #query NVARCHAR(MAX)
DECLARE #queryFinal NVARCHAR(MAX)
SET #query = ''
OPEN db_names
FETCH NEXT FROM db_names INTO #db_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = #query + 'SELECT ''' + #db_name + ''', id_salarie, nom, prenom, login COLLATE SQL_Latin1_General_CP1_CI_AS, password COLLATE SQL_Latin1_General_CP1_CI_AS, date_arrivee, date_depart, email COLLATE SQL_Latin1_General_CP1_CI_AS, persoMail COLLATE SQL_Latin1_General_CP1_CI_AS FROM [' + #db_name + '].dbo.utilisateurs WHERE dt_last_modif >= ''$date'' UNION '
FETCH NEXT FROM db_names INTO #db_name
END
DEALLOCATE db_names
SET #queryFinal = left(#query, len(#query)-6)
EXEC sp_executesql #queryFinal
More information about servers:
Server0 : 8 databases, 1050 users, no crash
Server1 : 88 databases, 18954 users, crash often
Server2 : 109 databases, 21897 users, crash often
Server3 : 26 databases, 1612 users, no crash
etc
Questions :
What is the issue with the script ? Any idea how I can stop crashs ?
And if no solution, how can I automatically recycle the pool?
Have you tried to make shure that the reader is cloesd after usage, too?
using(var reader = command.ExecuteReader()) { ...
I am not shure if the closed connection
using (var connection = new SqlConnection(connectionString))
takes care of the command and the reader resources.
I would do a few things here... if your problem is that persistent. First, I WOULD NOT generate one complete sql query trying to get data from all those tables all at once. Next, the queries are querying, and implied might be trying to LOCK the records associated with the query for POSSIBLE update... even though you are not probably going to be doing that.
I would add a WITH (NOLOCK) on the from tables.
select columns from yourTable WITH(NOLOCK) where...
This prevents any overhead with locking all the pages associated with the query.
Now, how to better handle your loop. Immediately BEFORE your fetch loop, I would create a temp table of the expected output results... something like
(unsure of column name lenghts for your structures...
create #C_TempResults
( fromDBName char(20),
id_salarie int,
nom char(10),
prenom char(10),
login char(10),
password char(10),
date_arivee datetime,
date_depart datetime,
email char(60),
persoMail char(60) );
then, in your loop where you are already cycling through all the tables you are querying, instead of building a concatenated SQL statement to execute at the end, just run ONE AT A TIME, and insert into the temp table like...
(same beginning to prepare your fetch cursor...)
BEGIN
SET #query = 'INSERT INTO #C_TempResults '
+ ' SELECT ''' + #db_name + ''' as fromDBName, id_salarie, nom, prenom, '
+ 'login COLLATE SQL_Latin1_General_CP1_CI_AS, '
+ 'password COLLATE SQL_Latin1_General_CP1_CI_AS, '
+ 'date_arrivee, date_depart, '
+ 'email COLLATE SQL_Latin1_General_CP1_CI_AS, '
+ 'persoMail COLLATE SQL_Latin1_General_CP1_CI_AS '
+ 'FROM [' + #db_name + '].dbo.utilisateurs WITH (NOLOCK) '
+ 'WHERE dt_last_modif >= ''$date'' ';
-- Run this single query now, get the data and release any "lock" resources
EXEC sp_executesql #queryFinal
-- now, get the next database to query from and continue
FETCH NEXT FROM db_names INTO #db_name
END
DEALLOCATE db_names
-- FINALLY, just run your select from the temp table that has everything all together...
select * from #C_TempResults;
-- and get rid of your "temp" table
drop table #C_TempResults;

Categories