SQL Query with multiple databases - tsql

I Have the following query
EXECUTE sp_MSForEachDB
'USE ?;
Select DB_NAME()AS DBName, count(DISTINCT TABLE.COLUMN) as "NEW_NAME"
FROM [dbo].[TABLE]'
Which gives me the results I want but for every database in my connection I get a separate output. Is there a way to put all these outputs from all the databases into one table. Sorry If I am not asking correctly sort of new to this...

if I understand you correctly this should work:
CREATE TABLE #Temp (DBName VARCHAR(250), NEW_NAME INT)
INSERT INTO #Temp
EXECUTE sp_MSForEachDB
'USE ?;
Select DB_NAME()AS DBName, count(DISTINCT TABLE.COLUMN) as "NEW_NAME"
FROM [dbo].[TABLE]'
SELECT * FROM #Temp
Below is an example of how this would work. I have modified the query so that it can be run on my machine as I don't have the table [dbo].[TABLE] in my databases:

Related

How to insert dynamic sql result into temp table without knowing the columns in advance

I am trying to insert result of dynamic sql into temp table. Important thing is i dont know the column names in advance. As per the SO suggestion the following should work
INSERT into #T1 execute ('execute ' + #SQLString )
also, omit the EXECUTE if the sql string is something other than a procedure.
However this is not working on SQL 2017
CREATE TABLE Documents(DocumentID INT, Status NVARCHAR(10))
INSERT INTO Documents(DocumentID,Status)
VALUES
(1,'Active'),
(2,'Active'),
(3,'Active'),
(4,'Active')
DECLARE #SQLString NVARCHAR(MAX)
SET #SQLString = 'SELECT * FROM Documents'
INSERT into #T1 execute ('execute ' + #SQLString )
I get error `Invalid object name '#T1'.`
Then i tried by omitting execute
INSERT into #T1 execute (#SQLString)
with same error `Invalid object name '#T1'.`
I should be able to do
SELECT * FROM #T1
You cannot do an INSERT INTO without having the table predefined. But what I believe you are asking is to do a SELECT INTO. I am aware of two ways of doing it. The first uses OPENROWSET, but I believe this has some drawbacks for security purposes. You could do the following:
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
SELECT *
INTO #T1
FROM OPENROWSET('SQLNCLI',
'Server=localhost;Trusted_Connection=yes;',
'SELECT * from <YOURDATABASE>.dbo.Documents')
Your second option is to create an inline TVF that will generate the table structure for you. So you could do the following:
CREATE FUNCTION getDocuments()
RETURNS TABLE
AS
RETURN
SELECT * from Documents
GO
SELECT * into #T1 FROM getDocuments()

insert value from two databases in postgresql

Can I perform a
select dblink_exec ('merg',E'insert into table1(col1,col2) select * from dblink(\'mc\',\'select distinct col1, col2 from table2\') as t(col1 bigint, col2 text)');
to be able to insert a select from a different database on the same server ?
I also tried to execute the second part into a view and then select from the view but did not work
All you need is to connect to one of the databases then execute
CREATE EXTENSION dblink
then just use:
select dblink_exec('dbname=table1', ....)

postgresql: INSERT INTO ... (SELECT * ...) - II [duplicate]

I'm not sure if its standard SQL:
INSERT INTO tblA
(SELECT id, time
FROM tblB
WHERE time > 1000)
What I'm looking for is: what if tblA and tblB are in different DB Servers.
Does PostgreSql gives any utility or has any functionality that will help to use INSERT query with PGresult struct
I mean SELECT id, time FROM tblB ... will return a PGresult* on using PQexec. Is it possible to use this struct in another PQexec to execute an INSERT command.
EDIT:
If not possible then I would go for extracting the values from PQresult* and create a multiple INSERT statement syntax like:
INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
Is it possible to create a prepared statement out of this!! :(
As Henrik wrote you can use dblink to connect remote database and fetch result. For example:
psql dbtest
CREATE TABLE tblB (id serial, time integer);
INSERT INTO tblB (time) VALUES (5000), (2000);
psql postgres
CREATE TABLE tblA (id serial, time integer);
INSERT INTO tblA
SELECT id, time
FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
AS t(id integer, time integer)
WHERE time > 1000;
TABLE tblA;
id | time
----+------
1 | 5000
2 | 2000
(2 rows)
PostgreSQL has record pseudo-type (only for function's argument or result type), which allows you query data from another (unknown) table.
Edit:
You can make it as prepared statement if you want and it works as well:
PREPARE migrate_data (integer) AS
INSERT INTO tblA
SELECT id, time
FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
AS t(id integer, time integer)
WHERE time > $1;
EXECUTE migrate_data(1000);
-- DEALLOCATE migrate_data;
Edit (yeah, another):
I just saw your revised question (closed as duplicate, or just very similar to this).
If my understanding is correct (postgres has tbla and dbtest has tblb and you want remote insert with local select, not remote select with local insert as above):
psql dbtest
SELECT dblink_exec
(
'dbname=postgres',
'INSERT INTO tbla
SELECT id, time
FROM dblink
(
''dbname=dbtest'',
''SELECT id, time FROM tblb''
)
AS t(id integer, time integer)
WHERE time > 1000;'
);
I don't like that nested dblink, but AFAIK I can't reference to tblB in dblink_exec body. Use LIMIT to specify top 20 rows, but I think you need to sort them using ORDER BY clause first.
If you want insert into specify column:
INSERT INTO table (time)
(SELECT time FROM
dblink('dbname=dbtest', 'SELECT time FROM tblB') AS t(time integer)
WHERE time > 1000
);
This notation (first seen here) looks useful too:
insert into postagem (
resumopostagem,
textopostagem,
dtliberacaopostagem,
idmediaimgpostagem,
idcatolico,
idminisermao,
idtipopostagem
) select
resumominisermao,
textominisermao,
diaminisermao,
idmediaimgminisermao,
idcatolico ,
idminisermao,
1
from
minisermao
You can use dblink to create a view that is resolved in another database. This database may be on another server.
insert into TABLENAMEA (A,B,C,D)
select A::integer,B,C,D from TABLENAMEB
If you are looking for PERFORMANCE, give where condition inside the db link query.
Otherwise it fetch all data from the foreign table and apply the where condition.
INSERT INTO tblA (id,time)
SELECT id, time FROM dblink('dbname=dbname port=5432 host=10.10.90.190 user=postgresuser password=pass123',
'select id, time from tblB where time>'''||1000||'''')
AS t1(id integer, time integer)
I am going to SELECT Databasee_One(10.0.0.10) data from Database_Two (10.0.0.20)
Connect to 10.0.0.20 and create DBLink Extenstion:
CREATE EXTENSION dblink;
Test the connection for Database_One:
SELECT dblink_connect('host=10.0.0.10 user=postgres password=dummy dbname=DB_ONE');
Create foreign data wrapper and server for global authentication:
CREATE FOREIGN DATA WRAPPER postgres VALIDATOR postgresql_fdw_validator;
You can use this server object for cross database queries:
CREATE SERVER dbonepostgres FOREIGN DATA WRAPPER postgres OPTIONS (hostaddr '10.0.0.10', dbname 'DB_ONE');
Mapping of user and server:
CREATE USER MAPPING FOR postgres SERVER dbonepostgres OPTIONS (user 'postgres', password 'dummy');
Test dblink:
SELECT dblink_connect('dbonepostgres');
Import data from 10.0.0.10 into 10.0.0.20
INSERT INTO tableA
SELECT
column1,
,column2,
...
FROM dblink('dbonepostgres', 'SELECT column1, column2, ... from public.tableA')
AS data(column1 DATATYPE, column2 DATATYPE, ...)
;
Here's an alternate solution, without using dblink.
Suppose B represents the source database and A represents the target database:
Then,
Copy table from source DB to target DB:
pg_dump -t <source_table> <source_db> | psql <target_db>
Open psql prompt, connect to target_db, and use a simple insert:
psql
# \c <target_db>;
# INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
At the end, delete the copy of source_table that you created in target_table.
# DROP TABLE <source_table>;

Can I Use Order by to sort Stored Procedure results?

Simply, I have this SQL statment:
EXEC xp_cmdshell 'tasklist'
can we order or filter the results by using order by or where?
Thanks,
I checked jamietre link, and this is the complete answer:
Create table #MyTempTable
(output varchar(max))
INSERT INTO #MyTempTable
EXEC xp_cmdshell 'tasklist'
select * from #MyTempTable where output like 'ie%' order by output
Thanks for all...
You need to output the results into a temporary table first. This should show you how to do it
Insert results of a stored procedure into a temporary table
not directly. You can insert exec into a temp table or table variable and then sort that though
When running the above query multiple times, you might run into this error: There is already an object named '#MyTempTable' in the database.
To mitigate this you can use a DROP IF EXISTS statement as follows before creating the temp table.
IF OBJECT_ID(N'tempdb..#MyTempTable') IS NOT NULL
BEGIN
DROP TABLE #MyTempTable
END
CREATE TABLE #MyTempTable
(OUTPUT VARCHAR(max))
INSERT INTO #MyTempTable
EXEC xp_cmdshell 'tasklist'
SELECT * FROM #MyTempTable WHERE OUTPUT like 'ie%' ORDER BY OUTPUT

How to create DDL trigger to all databases in SQL Server 2005 instance

I am going to create a DDL trigger to all databases in SQL Server instance. I'd like to do it in one run instead of many runs for each database.
Below are the two T-SQL statements I need to execute:
-- Create table
use <dbname>
GO
CREATE TABLE dbo.ChangeAttempt
(EventData xml NOT NULL,
AttemptDate datetime NOT NULL DEFAULT GETDATE(),
DBUser char(50) NOT NULL)
GO
-- Create DDL trigger
use <dbname>
GO
CREATE TRIGGER db_trg_ObjectChanges
ON DATABASE
FOR ALTER_PROCEDURE, DROP_PROCEDURE,
ALTER_INDEX, DROP_INDEX,
ALTER_TABLE, DROP_TABLE, ALTER_TRIGGER, DROP_TRIGGER,
ALTER_VIEW, DROP_VIEW, ALTER_SCHEMA, DROP_SCHEMA,
ALTER_ROLE, DROP_ROLE, ALTER_USER, DROP_USER
AS
SET NOCOUNT ON
INSERT dbo.ChangeAttempt
(EventData, DBUser)
VALUES (EVENTDATA(), USER)
GO
My question is: how can I programmaticaly create DDL trigger in one run?
why do you need one run? this is the only way to do it.
Msg 111, Level 15, State 1, Line 2
'CREATE TRIGGER' must be the first statement in a query batch.
run the output generated by this:
DECLARE #DatabaseName varchar(500)
DECLARE #Database_id int
DECLARE #Query varchar(8000)
DECLARE #CRLF char(2)
SET #CRLF=CHAR(13)+CHAR(10)
---MODIFY THIS TO INCLUDE THE DATABASES THAT YOU WANT TO WORk ON
---MODIFY THIS TO INCLUDE THE DATABASES THAT YOU WANT TO WORk ON
select #Database_id=MIN(database_id) from sys.databases where database_id IN (5,7,8,6)
WHILE #Database_id IS NOT NULL
BEGIN
SELECT #DatabaseName=name from sys.databases where database_id=#Database_id
SET #Query='-- Create table'+#CRLF+#CRLF
+'use '+#DatabaseName+#CRLF
+' GO'+#CRLF
+' CREATE TABLE dbo.ChangeAttempt'+#CRLF
+' (EventData xml NOT NULL,'+#CRLF
+' AttemptDate datetime NOT NULL DEFAULT GETDATE(),'+#CRLF
+' DBUser char(50) NOT NULL)'+#CRLF
+'GO'+#CRLF+#CRLF
+'-- Create DDL trigger '+#CRLF+#CRLF
+'use '+#DatabaseName+#CRLF
+'GO'+#CRLF
+'CREATE TRIGGER db_trg_ObjectChanges'+#CRLF
+'ON DATABASE'+#CRLF
+'FOR ALTER_PROCEDURE, DROP_PROCEDURE,'+#CRLF
+' ALTER_INDEX, DROP_INDEX,'+#CRLF
+' ALTER_TABLE, DROP_TABLE, ALTER_TRIGGER, DROP_TRIGGER,'+#CRLF
+' ALTER_VIEW, DROP_VIEW, ALTER_SCHEMA, DROP_SCHEMA,'+#CRLF
+' ALTER_ROLE, DROP_ROLE, ALTER_USER, DROP_USER'+#CRLF
+'AS'+#CRLF
+'SET NOCOUNT ON'+#CRLF
+'INSERT dbo.ChangeAttempt'+#CRLF
+'(EventData, DBUser)'+#CRLF
+'VALUES (EVENTDATA(), USER)'+#CRLF
+'GO'+#CRLF
PRINT #Query
---MODIFY THIS TO INCLUDE THE DATABASES THAT YOU WANT TO WORk ON
---MODIFY THIS TO INCLUDE THE DATABASES THAT YOU WANT TO WORk ON
select #Database_id=MIN(database_id) from sys.databases WHERE database_id IN (5,7,8,6) AND database_id>#Database_id
END
EDIT
to determine what databases to generate scripts for do the following:
run this query:
select database_id,name from sys.databases
find all of the databases you want to run the scripts for
change my above script in two places (before loop & at bottom in loop) so all of the database_id that you want are in the following code section:
WHERE database_id IN (AAA,BBB,CCC,DDD,....)
You could use sp_MSforeachdb.
Something like this
sp_MSforeachdb
'
CREATE TABLE ?.dbo.ChangeAttempt
etc. etc. etc.
'
sp_MSforeachdb
'
CREATE TRIGGER ?.dbo.db_trg_ObjectChanges
etc. etc. etc.
'
I haven't tested this, in theory I'd expect it to work though. You want to make sure you exclude the system databases though.