the copy into command returns an output dataset.
CTAS can create a table from the results of a query.
combining the two, we would expect to get the list of loaded files into a new table.
CREATE TABLE MY_LOADED_FILES
AS
COPY INTO mytable
FROM #my_int_stage;
However, this returns:
SQL compilation error: syntax error line 3 at position 0 unexpected 'copy'.
What am I doing wrong?
It doesn't look like you can put a COPY INTO statement inside another statement unfortunately. There is a way to do this however by using the result_scan function to return the results of the previous query.
copy into test_database.public.test_table from #my_int_stage;
create temporary table test_database.public.test_table_results as (
select * from table(result_scan(LAST_QUERY_ID()))
);
Of course you need to make sure the second query runs in the same session as the copy statement and also that it is run directly after the copy statement. Alternatively you can use the query id with the result_scan.
If you want to see which files were loaded why don't you just look at the copy_history of the table?
Related
I am creating a BQ Stored Procedure to truncate all the tables in a dataset. I have a 2 step process. Step 1 identifies all the matching tables. Step 2 is expected to iterate thru each table and truncate.
I have the following code to achieve this:
for record in
( select TABLE_NAME
from <staging_dataset>.INFORMATION_SCHEMA.TABLES
)
DO
execute immediate
"truncate table #tab" using record.TABLE_NAME as tab;
END FOR;
The Error that I am running into is in the Execute Immediate piece.
Invalid EXECUTE IMMEDIATE sql string `truncate table #tab`, Syntax error: Unexpected "#" at [8:3]
I tried replacing the #tab with ? placeholder and see a similar error. What am I doing wrong?
Is there another way to achieve the same result?
Strange; it seems DML doesn't work with USING. Queries work fine.
Try using CONCAT to build your dynamic query string:
CONCAT("truncate table ", record.TABLE_NAME);
I opened a report I started in BIDS in MS SQL Server Report Builder 3.0, as I read an answer here on SO that said that was the easiest way to create a table containing all the values in a Dataset.
So I opened my .rdl file there, selected the Insert tab, then Table > Table Wizard, and the dataset from the "Choose an existing dataset in this report or a shared dataset" list.
When I select the "Next" button of the wizard, though, all lists are empty (Available fields, Column groups, Row groups, Values).
If I select "Next" again, I get, "The values field list must contain at least one field."
Those are auto-populated, though, and, as written above, are as empty as a politican's brain.
Is it because my dataset is a StoredProc, and returns data from a temp table? If so, is there a workaround?
Note: I also tried the Matrix > Matrix Wizard, with the same results.
UPDATE
Also and doubtless relatedly (no pun intended), when I try to run the report from within ReportBuilder, I see:
What a revoltin' development!
UPDATE 2
And when I return to BIDS to work on the project and try to add an Expression in a Matrix, in the Edit Expression dialog, on selecting the Dataset of interest, I get, " dataset has no fields."
Ay, caramba!
UPDATE 3
In response to lrb's answer: I don't know if my SP is really unparseable or not; it does return values from a temp table - Here is the end of it:
SELECT PLATYPUSDESCRIPTION, WEEK1USAGE, WEEK2USAGE, USAGEVARIANCE,
WEEK1PRICE, WEEK2PRICE, PRICEVARIANCE, PRICEVARIANCEPERCENTAGE
FROM #TEMPCOMBINED
ORDER BY PLATYPUSDESCRIPTION;
Could that (using a temp table) be the problem?
UPDATE 4
When adding an Expression to a textbox like so:
=Fields!PLATYPUSDESCRIPTION.Value
...I get the following fingerwag on the Preview tab:
The definition of the report 'bla' is invalid. The Value expression for the textbox 'textbox4' refers to the field 'PLATYPUSDESCRIPTION'. Report item expressions can only refer to fields within the current data set scope or, if inside an aggregate, the specified data set scope.
Surely there's a way to use results from temp tables in an SSRS report, no es cierto?
This will happen when the query or stored procedure can not be parsed with certainty. For example, if your data set is a store procedure that returns something like the following:
IF(#SomVariable=1)
SELECT 1,2,3,4
ELSE
SELECT 'A','B','C'
The above logic in a SP would be horrible, however, the field name and datatypes can not be determined. The same holds true in other edge case scenarios.
What you can do for a work around is to trick the parser by modifying your sp and offering up a clean return statement, then changing the sp back to its original form. Since the metadata is persistent until the next refresh, your values will hold. NOTE : If the problem occurs when returning temporary tables in your dataset see #4 below.
1. Modify your existing stored procedure
ALTER PROCEDURE MyProcedureThatDoesNotParse()
AS
BEGIN
/*COMMENT OUT CURRENT SP LOGIC
...
*/
SELECT
MyField1=1,
MyField2='String',
MyField3=0.01
END
2. IN SSRS Refresh the fields for your dataset.
NOTE : You will see MyField1,MyField2 and MyField3 in the fields list.
3. Revert the changes to your stored procedure.
4. For queries or SP's that return a local #temporary table, global ##temporary table or a table valued #variable, it seems that aliasing the temp structure works. I.E
SELECT * FROM #TABLE --Does not always parse in SSRS
SELECT * FROM #TABLE T --Seems to be able to be parsed by SSRS
Change command type on the report builder, choose " text " and write exec yourprocedurename. It will work
I encounter some strange behavior with a dynamic SQL Query.
In a stored procedure I construct an insert query string out of multiple Strings. I execute the insert query in the SP like that - due to single nvarchar length restrictions.
EXEC(#QuerySelectPT+#QueryFromPT+#QueryFromPT)
If I print each part of the query, put these parts together and execute them manually in Management Studio the query works fine and inserts the data. But, if i execute the query in the EXEC() Method in the stored procedure, I get a
Column name or number of supplied values does not match table definition.
Error Message.
Did multiple check on the amount, spelling of columns in my query and in my insert table, but I have not found any differences so far.
Any advices?
Your count of columns for insert are different from count of columns for select. Print the statement before exec and find the error.
It as shot in the dark but seen you are telling the queries are valid and if you build the final query manually and it is working, the issue could be caused by string truncation.
Could you try:
EXEC(CAST(#QuerySelectPT AS VARCHAR(MAX))+#QueryFromPT+#QueryFromPT);
Also, as the Management Studio's message tab and selects are limited to 4000 symbols I think, you can test if the whole query is assembled correctly like this:
SELECT CAST(#QuerySelectPT+#QueryFromPT+#QueryFromPT AS XML)
I have a table and it has 500 rows. I want to retrieve only 10 rows and i want to insert into another table using control flow only. Through data flow task we can use OLEDB source and OLEDB destination. But i want result in such a way that by using execute sql task and for each loop. Is it possible to do in that way? My Idea is, get the set of ten records and and by using foreach loop iterate to every row and insert into the table by using execute sql task. The destination table need to create on the fly. I tried with some approach but not moving towards. Please find the image file.
Example taken from Northwind
Create variables (in variable collection) which represent the columns in the table which u ll create at runtime
Example :-
Customer_ID as string
Order_Id as int
Then u need to create Execute SQL Task and write the below query to select first 10 rows
Select top 10* from orders
Use FullResultSet and in Result Set configuration store the table rows in a variableName :- User::Result ResultName:0
Drop one Execute SQL Task and create a table on fly
IF OBJECT_ID('myOrders') IS not NULL
drop table myOrders
Create table myOrders
(OrderID int,
CustomerID varchar(50)
)
combine the 2 flows from Execute sql task and connect it to the Foreach loop
Drag a foreach loop .In collection use enumerator type as Foreach ADO Enumerator
In enumerator configuration select user::Result variable which stores the top 10 rows from the execute sql task and select the radio button " Rows in the first table"
In variable mapping ,map the column variables which u have created in the first step and the index will 0 for first column and 1 for 2nd column
Drag a execute sql task inside a foreach loop and write the below query :
Insert into myOrders( OrderID,CustomerID)
values
(?,?)
Map the parameters using parameter mapping configuration in execute sql task
VariableName : OrderID Direction : Input DataType=Long ParamterName=0
VariableName : CustomerID Direction : Input DataType=varchar ParamterName=1
I hope you are doing this on a "study-mode". There is no reason why to do this on the control flow over the data flow.
Anyway, your print screen is correct, I would just add another execute sql task in the beginning to create your destination table.
Then, your execute sql task should have the query to bring the 10 rows you want, its result set should be set to "Full result set" and on the resultset tab you should map the result set to a variable like this:
and configure your foreach loop container like this:
on each loop of the foreach you will have access to the values on the variables, then you can use another execute sql task to insert then on the new crated table
I am trying to query between two servers which have identical tables (used the same create statement for both). When I try to insert the results from Server A to Server B I get an error indicating "Column name or number of supplied values does not match table definition."
Query run on server A
Insert into ServerB.Database1.dbo.Table1
Select *
from Table1
The error is clear, but what isn't clear is the reason that it is generated. The definitions of the two tables are identical. What I was finally able to isolate was a table name that starts with a numeric value is not being recognized.
When I run this on ServerA:
Select *
from ServerB.Database1.dbo.Table1
The field with the numeric value is not shown in the results set of they query. The short term fix was to rename the field in the database, but why is this happening?
I am curious about the collation too, but really the answer is to wrap the object names in square brackets. i.e. SELECT [1col], [2col], [etc] FROM [1database].[2owner].[3table]. This way SQL with recognize each as an object name and not a function.
One other thing to keep in mind is to not use splat (*) in your select statement, this has potential problem of it's own. For example, you could run into an error in your Insert if the ServerA's table1 structure was change and ServerB's table one stayed the same.