How to join two tables from different database in MS SQL Azure? - sql-server

I have two different tables in two different databases. Need to join both the table and get results using query
1) reports - report_id, report_name, description
table reports is present in database 'A'
2) report_owners - report_id, report_owner
table report_owners is present in database 'B'
tried following query for joining the tables but it's throwing error ( Reference to server and/ database is not supported in this version of SQL server).
Query:
select * from [A].[dbo].['reports'] as all_reports
INNER JOIN
select * from [B].[dbo].['report_owners'] as all_owner
ON all_report.report_id = all_owners.report_id
Note: from Database 'A' have access for cross query functionality for database 'B'
Anyone please help me to solve this issue?

You need to use elastic queries to perform cross database queries. See the following example:
Customerinformation (remote db)
CREATE TABLE dbo.CustomerInformation (CustomerID int identity(1,1) , CustomerName nvarchar(255));
DECLARE #i int = 1;
WHILE #i < 20000
BEGIN
INSERT INTO CustomerInformation(CustomerName)
VALUES ('Frodo');
SET #i += 1;
END
On the database that will use the external table
CREATE TABLE OrderInformation(OrderId Int identity(1,1), CustomerId int,Ordervalue int);
SET NOCOUNT ON;
DECLARE #i int = 1;
WHILE #i < 200
BEGIN
INSERT INTO OrderInformation(CustomerId,Ordervalue)
Values (#I,111);
set #i += 1;
END
CREATE EXTERNAL TABLE [dbo].CustomerInformation(
CustomerID [int],
CustomerName nvarchar(255))
WITH
(
DATA_SOURCE = Stackoverflow
);
Query the remote table like this.
SELECT o.OrderId, c.CustomerID, c.CustomerName
FROM OrderInformation o
JOIN CustomerInformation c ON o.CustomerID = c.CustomerID
WHERE o.OrderId = 155

Related

Creating a Query for each row in a SQL Table

I have a schema in my SQL table out of which some table has a time value stamp (same column name 'timestamp' in all the tables in the schema) and I need to create a new table which will give the latest time stamp for each such table. I have achieved a part which will give me a table with 2 columns, one the table name column and another column which gives the query for each table which if runs will give me the latest timeStamp for each table in table name Column. The script I used is as follows and I show 3 rows as an example:
WITH CTE AS
(
SELECT
CONCAT(schema_name(t.schema_id), '.',t.name) AS table_name,
c.name AS 'time_stamp'
FROM
sys.tables t
INNER JOIN
sys.columns c ON c.object_id = t.object_id
WHERE
schema_name(t.schema_id) = 'PROD'
AND c.name = 'timestamp'
)
SELECT table_name, time_stamp
INTO #TEMP_TABLE
FROM CTE
DECLARE #i int = 1, #c int = (SELECT COUNT(*) FROM #TEMP_TABLE)
DECLARE #Result TABLE
(
tName varchar(500),
tStamp varchar(500)
)
WHILE (#i <= #c)
BEGIN
INSERT INTO #Result
SELECT
table_name,
'SELECT MAX('+ time_stamp +') FROM ' + table_name
FROM #TEMP_TABLE;
SET #i = #i + 1
END
DROP TABLE #TEMP_TABLE
SELECT * FROM #RESULT
When I run this script I get the following table (3 rows shown as an illustration)
My output (O)
tName tStamp
-----------------------------------------------------------
PROD.table_A SELECT MAX(time_stamp) FROM PROD.table_A
PROD.table_B SELECT MAX(time_stamp) FROM PROD.table_B
PROD.table_C SELECT MAX(time_stamp) FROM PROD.table_C
However what I want is the value of the query in the tStamp column and not the query string. So actually the output table should look like (say assuming the query in each of the above rows in column tStamp. I put in some max values as an example when we run each query in tStamp column)
My final expected output (F)
tName tStamp
------------------------------------------
PROD.table_A 2021-10-12 14:20:56.000
PROD.table_B 2021-11-01 19:04:35.000
PROD.table_C 2021-10-23 08:07:12.000
I am in a limbo at this stage not sure, how to get the table F from table O. So I will really appreciate any help. If it can be possible to tweak something which I am doing to get directly the output table F or if we can work on the table O to get to table F anything can help.
Thanks in advance.
If this is a one shot thing, I would consider just using a macro (vim, excel) to generate the query text for each table using your CTE results and then paste it back in and run.
If not, you could consider some of the suggestions for dynamic sql in this article: [https://www.mssqltips.com/sqlservertip/1160/execute-dynamic-sql-commands-in-sql-server/][1]

How to fiind out the missing records (ID) from an indexed [order] table in sql

I have a table [Order] that has records with sequential ID (in odd number only, i.e. 1,3,5,7...989, 991, 993, 995, 997, 999), it is seen that a few records were accidentally deleted and should be inserted back, first thing is to find out what records are missing in the current table, there are hundreds of records in this table
Don't know how to write the query, can anyone kindly help, please?
I am thinking if I have to write a stored procedure or function but would be better if I can avoid them for environment reasons.
Below peuso code is what I am thinking:
set #MaxValue = Max(numberfield)
set #TestValue = 1
open cursor on recordset ordered by numberfield
foreach numberfield
while (numberfield != #testvalue) and (#testvalue < #MaxValue) then
Insert #testvalue into #temp table
set #testvalue = #textvalue + 2
Next
Next
UPDATE:
Expected result:
Order ID = 7 should be picked up as the only missing record.
Update 2:
If I use
WHERE
o.id IS NULL;
It returns nothing:
Since I didn't get a response from you, in the comments, I've altered the script for you to fill in accordingly:
declare #id int
declare #maxid int
set #id = 1
select #maxid = max([Your ID Column Name]) from [Your Table Name]
declare #IDseq table (id int)
while #id < #maxid --whatever you max is
begin
insert into #IDseq values(#id)
set #id = #id + 1
end
select
s.id
from #IDseq s
left join [Your Table Name] t on s.id = t.[Your ID Column Name]
where t.[Your ID Column Name] is null
Where you see [Your ID Column Name], replace everything with your column name and the same goes for [Your Table Name].
I'm sure this will give you the results you seek.
We can try joining to a number table, which contains all the odd numbers which you might expect to appear in your own table.
DECLARE #start int = 1
DECLARE #end int = 1000
WITH cte AS (
SELECT #start num
UNION ALL
SELECT num + 2 FROM cte WHERE num < #end
)
SELECT num
FROM cte t
LEFT JOIN [Order] o
ON t.num = o.numberfield
WHERE
o.numberfield IS NULL;

How do I loop through a table, search with that data, and then return search criteria and result to new table?

I have a set of records that need to be validated (searched) in a SQL table. I will call these ValData and SearchTable respectively. A colleague created a SQL query in which a record from the ValData can be copied and pasted in to a string variable, and then it is searched in the SearchTable. The best result from the SearchTable is returned. This works very well.
I want to automate this process. I loaded the ValData to SQL in a table like so:
RowID INT, FirstName, LastName, DOB, Date1, Date2, TextDescription.
I want to loop through this set of data, by RowID, and then create a result table that is the ValData joined with the best match from the SearchTable. Again, I already have a query that does that portion. I just need the loop portion, and my SQL skills are virtually non-existent.
Suedo code would be:
DECLARE #SearchID INT = 1
DECLARE #MaxSearchID INT = 15000
DECLARE #FName VARCHAR(50) = ''
DECLARE #FName VARCHAR(50) = ''
etc...
WHILE #SearchID <= #MaxSearchID
BEGIN
SET #FNAME = (SELECT [Fname] FROM ValData WHERE [RowID] = #SearchID)
SET #LNAME = (SELECT [Lname] FROM ValData WHERE [RowID] = #SearchID)
etc...
Do colleague's query, and then insert(?) search criteria joined with the result from the SearchTable in to a temporary result table.
END
SELECT * FROM FinalResultTable;
My biggest lack of knowledge comes in how do I create a temporary result table that is ValData's fields + SearchTable's fields, and during the loop iterations how do I add one row at a time to this temporary result table that includes the ValData joined with the result from the SearchTable?
If it helps, I'm using/wanting to join all fields from ValData and all fields from SearchTable.
Wouldn't this be far easier with a query like this..?
SELECT FNAME,
LNAME
FROM ValData
WHERE (FName = #Fname
OR LName = #Lname)
AND RowID <= #MaxSearchID
ORDER BY RowID ASC;
There is literally no reason to use a WHILE other than to destroy performance of the query.
With a bit more trial and error, I was able to answer what I was looking for (which, at its core, was creating a temp table and then inserting rows in to it).
CREATE TABLE #RESULTTABLE(
[feedname] VARCHAR(100),
...
[SCORE] INT,
[Max Score] INT,
[% Score] FLOAT(4),
[RowID] SMALLINT
)
SET #SearchID = 1
SET #MaxSearchID = (SELECT MAX([RowID]) FROM ValidationData
WHILE #SearchID <= #MaxSearchID
BEGIN
SET #FNAME = (SELECT [Fname] FROM ValidationData WHERE [RowID] = #SearchID)
...
--BEST MATCH QUERY HERE
--Select the "top" best match (order not guaranteed) in to the RESULTTABLE.
INSERT INTO #RESULTTABLE
SELECT TOP 1 *, #SearchID AS RowID
--INTO #RESULTTABLE
FROM #TABLE3
WHERE [% Score] IN (SELECT MAX([% Score]) FROM #TABLE3)
--Drop temp tables that were created/used during best match query.
DROP TABLE #TABLE1
DROP TABLE #TABLE2
DROP TABLE #TABLE3
SET #SearchID = #SearchID + 1
END;
--Join the data that was validated (searched) to the results that were found.
SELECT *
FROM ValidationData vd
LEFT JOIN #RESULTTABLE rt ON rt.[RowID] = vd.[RowID]
ORDER BY vd.[RowID]
DROP TABLE #RESULTTABLE
I know this could be approved by doing a join, probably with the "BEST MATCH QUERY" as an inner query. I am just not that skilled yet. This takes a manual process which took hours upon hours and shortens it to just an hour or so.

How can I know that a Trigger is fired or not?

I am using SQL Server 2008 R2 on a windows 7 machine. I have a trigger that should be fired on an insert but unfortunately it does not. I do not have the SQL Profiler because I have an express edition. Is there any other way to see what is going wrong?. The insert into the table teams is done with the Import Wizard of SQL Server, an i import from .CSV into a table.
CREATE TRIGGER teams.process ON teams
AFTER INSERT
AS
BEGIN
DECLARE #homeTeamId INT
DECLARE #awayTeamId INT
DECLARE #maxTeamId INT
DECLARE #matchId INT
SELECT #maxTeamId = 0
SELECT #maxTeamId = ISNULL(MAX(teamId), 0) from tblTeams
--- Check if home team has already been inserted into the table.
SELECT #homeTeamId = -1
SELECT
#homeTeamId = teamId
FROM
tblTeams t
JOIN inserted i
ON t.teamName = i.hometeam
IF (#homeTeamId = -1)
BEGIN
SELECT #homeTeamId = #maxTeamId + 1
SELECT #maxTeamId = #maxTeamId + 1
INSERT INTO tblTeams SELECT #homeTeamId, i.hometeam FROM inserted i
END
--- Check if away team has already been inserted into the table.
SELECT #awayTeamId = -1
SELECT
#awayTeamId = teamId
FROM
tblTeams t
JOIN inserted i
ON t.teamName = i.awayteam
IF (#awayTeamId = -1)
BEGIN
SELECT #awayTeamId = #maxTeamId + 1
SELECT #maxTeamId = #maxTeamId + 1
INSERT INTO tblTeams SELECT #awayTeamId, i.awayteam FROM inserted i
END
-- insert a record into the matches table with the home team ID and away team ID.
SELECT #matchId = 0
SELECT #matchId = ISNULL(MAX(MatchId), 0) FROM tblMatches
INSERT INTO tblMatches
SELECT #matchId + 1, #homeTeamId, #awayTeamId, i.score
FROM inserted i
END
Okay. If we can change the table definitions of tblTeams and tblMatches slightly, so that they maintain their own ID columns using IDENTITY, then we can fix the trigger to be safe for multi-row inserts:
create table teams (
hometeam varchar(10) not null,
awayteam varchar(10) not null,
score int not null
)
create table tblteams (
teamId int IDENTITY(1,1) not null,
teamName varchar(10) not null
)
create table tblmatches (
matchId int IDENTITY(1,1) not null,
HomeTeamID int not null,
AwayTeamID int not null,
Score int not null
)
go
CREATE TRIGGER process ON teams
AFTER INSERT
AS
SET NOCOUNT ON
declare #TeamIDs table (TeamID int not null,TeamName varchar(10) not null)
;with AllTeams as (
select hometeam as teamName from inserted
union
select awayteam from inserted
)
merge into tblTeams tt using AllTeams at on tt.teamName = at.teamName
when matched then update set teamName = at.teamName
when not matched then insert (teamName) values (at.teamName)
output inserted.TeamID,inserted.teamName into #TeamIDs;
insert into tblmatches (HomeTeamID,AwayTeamID,Score)
select ht.TeamID,at.TeamID,i.Score
from inserted i
inner join #TeamIDs ht on i.hometeam = ht.TeamName
inner join #TeamIDs at on i.awayteam = at.TeamName
GO
And then we test it out:
insert into teams (hometeam,awayteam,score) values
('abc','def',10),
('def','ghi',5),
('jkl','mno',7)
go
insert into teams (hometeam,awayteam,score) values
('abc','ghi',19),
('pqr','stu',11)
go
select * from tblteams
select * from tblmatches
The issue with your existing trigger is it didn't cope with inserted containing multiple rows - the trigger is fired once per statement, not once per row. So e.g. these line are wrong:
SELECT #homeTeamId = #maxTeamId + 1
SELECT #maxTeamId = #maxTeamId + 1
INSERT INTO tblTeams SELECT #homeTeamId, i.hometeam FROM inserted i
Since there might be multiple homeTeam values to deal with.
It also didn't deal well with concurrency - two calls to the trigger happening in parallel might end up with the same #maxTeamId value - and then attempt to insert rows into tblTeam with the same TeamId values - whereas using IDENTITY columns, SQL Server deals with this for us automatically.
The only slight fudge in the above is using MERGE to insert new teams - the WHEN MATCHED line will do a No-Op UPDATE for existing rows (since we know the teamName matches on both sides), but it's a nice trick to do the lookup of existing rows and INSERT of new rows in a single statement.
I've just realised that you've said that you're using the Import data wizard. I have a feeling that the SSIS Package that it generates creates a destination using Fast Load, and doesn't specify FIRE_TRIGGERS. That could scupper you also.
You could either generate the package using the wizard, then edit the properties, or use the wizard to insert into a staging table, then do a plain INSERT/SELECT from that table into our teams table, and let the trigger fire that way.
Bulk insert wizards / data import wizards usually bypass triggers on the destination table.

TSQL - Optimizing Full Text Search query with temp table

To make it short I have a full text search query that does a company search on a single table. Once the search is complete I pull extra stats from the result such as Top 5 titles, top 5 locations etc...
How can this query be optimized it currently takes about 5 seconds to execute on < 25,000 rows and based on the execution plan its mostly on the last 3 select statements.
SQL SERVER: 2005. I can upgrade to 2008 but I've heard there are more performance issues with SQL 2008.
Help is greatly appreciated.
CREATE PROCEDURE [usp_Company_Search]
#KeywordNear as varchar(250),
#LocationNear as varchar(250) = null,
#PageIndex as int,
#Pagesize as int
AS
BEGIN
DECLARE #tbl TABLE
(
row int,
[Rank] int,
CompanyID int,
CompanyDesc text,
Title nvarchar(150),
Company nvarchar(150),
Category nvarchar(50),
Source nvarchar(50),
URI nvarchar(250),
Location varchar(60),
DateCreated nvarchar(50)
)
IF (#LocationNear is not null) BEGIN
WITH CompanySearch as
(
SELECT ROW_NUMBER() OVER (ORDER BY rs.rank desc) as row,
rs.Rank as [Rank],
J.CompanyID,
J.CompanyDesc,
J.Title,
J.Company,
J.Category,
J.Source,
J.URI,
J.Location,
J.DateCreated
FROM Company J
INNER JOIN
CONTAINSTABLE (Company,RawStripped, #KeywordNear) rs
ON J.Companyid = rs.[KEY] AND
CONTAINS (Location, #LocationNear)
)
insert into #tbl select * from CompanySearch
SELECT
CompanySearch.[Rank],
CompanySearch.CompanyID,
CompanySearch.CompanyDesc,
CompanySearch.Title,
CompanySearch.Company,
CompanySearch.Category,
CompanySearch.Source,
CompanySearch.URI,
CompanySearch.Location,
CompanySearch.DateCreated
FROM #tbl as CompanySearch
WHERE CompanySearch.row between (#PageIndex - 1) * #PageSize + 1 and #PageIndex*#PageSize
END
ELSE
BEGIN
WITH CompanySearch as
(
SELECT ROW_NUMBER() OVER (ORDER BY rs.rank desc) as row,
rs.Rank,
J.CompanyID,
J.CompanyDesc,
J.Title,
J.Company,
J.Category,
J.Source,
J.URI,
J.Location,
J.DateCreated
FROM Company J
INNER JOIN
CONTAINSTABLE (Company,RawStripped, #KeywordNear) rs
ON J.Companyid = rs.[KEY]
)
insert into #tbl select * from CompanySearch
SELECT
CompanySearch.Rank,
CompanySearch.CompanyID,
CompanySearch.CompanyDesc,
CompanySearch.Title,
CompanySearch.Company,
CompanySearch.Category,
CompanySearch.Source,
CompanySearch.URI,
CompanySearch.Location,
CompanySearch.DateCreated
FROM #tbl as CompanySearch
WHERE CompanySearch.row between (#PageIndex - 1) * #PageSize + 1 and #PageIndex*#PageSize
END
SELECT Max(row) as RecordCount from #tbl
select top 5 title, count(title) as cnt from #tbl group by title order by cnt desc
SELECT top 5 Location, count(location) as cnt from #tbl group by location order by cnt desc
SELECT top 5 Company, count(company) as cnt from #tbl group by company order by cnt desc
END
Your execution plan results may be deceiving. In SQL 2005, the fulltext engine is an external service, so SQL cannot accurately report on what's happening in that piece of the puzzle.
I'm not sure what performance issues you've heard of in 2008, but in 2008 the fulltext engine becomes fully integrated with the database, making it much more efficient in a case like yours where you're joining a database table against a set of fulltext results. If upgrading is an option for you, I'd encourage you to pursue that option.
See: SQL Server 2008 Full-Text Search: Internals and Enhancements

Resources