dear brothers-in-codes =)
By now i'm using Power Query for quite a long time to communicate with SQL Server.
I already now how to sent data from Excel Table to SQL Table using INSERT... , UPDATE... , DELETE... instructions.
Yet currently i faced a problem, when i was trying to
Create table
Populate it with the data from Excel Table.
I understood that just have no idea, how to send 2 sequential Queries with
CREATE SCHEMA... & CREATE TABLE... instructions
with INSERT INTO... instruction, passing to this Query Table Columns as parameters
Currently my PQ Function looks like this (the commented part is something that I do manually in SSMS before launching the PQ Function from Excel):
(mCourses, mSQLCourseCode, mOwnToolkit, mTuition, mToolkit, mTuitionDeposit, mInstalments, mAcadDuration, mType, mDateOfUpload)=>
let
Source = Sql.Database("<a.d.re.ss>", "<DB.Name>",
[Query="
use EnvirotechFinance
--GO
--if schema_id('price') is null
--execute('CREATE SCHEMA price');
--GO
--drop table if exists price.Price
--Create table price.Price
--(
-- Courses nvarchar(255),
-- SQLCourseCode nvarchar(255),
-- OwnToolkit int,
-- Tuition decimal(12,5),
-- Toolkit decimal(12,5),
-- TuitionDeposit decimal(12,5),
-- Instalments int,
-- AcadDuration int,
-- Type int,
-- DateOfUpload date
--)
insert into price.Price
( Courses,
SQLCourseCode,
OwnToolkit,
Tuition,
Toolkit,
TuitionDeposit,
Instalments,
AcadDuration,
Type,
DateOfUpload
)
Values ('" & mCourses &"', '"& mSQLCourseCode &"', '"& mOwnToolkit &"', '"& mTuition &"', '"& mToolkit &"',
'"& mTuitionDeposit &"','"& mInstalments &"', '"& mAcadDuration &"', '" & mType & "', '" & mDateOfUpload & "')
"])
in
Source
You could make another step which depends on the Source step that also calls Sql.Database with the second query.
However, using Power Query in this fashion is highly discouraged. Native queries should be used for complex read queries or stored procedures, but they should not be used for modifying the database itself. In other words, running INSERT or DELETE operations in Power Query should be avoided. This is because Power Query may re-evaluate the query multiple times, so you can end up inserting a row several more times than you expected.
Related
I am currently making a project for school where I have to make a program where I can create orders in.
When I try to create orders I get this error returned to me.
Error converting Data Type Nvarchar to Int.
In advance I'm sorry if this is a really basic question that is easely spotted. Me and my project members are beginning programmers but we simply cannot spot where this goes wrong.
The code we execute in vba is this :
Set rs = DbConn.Execute("EXEC spOrderPlaatsen '" & Me.tbTijd & "', " & Me.klantnr & ", '" & Me.tbOphaaldatum & "', '" & Me.tbAfleverdatum & "', '" & Me.tbOphaaladres & "', " & Me.tbPalletnr & ", " & Me.tbAantalpallets & "")
This code execute's our Stored procedure.
The stored procedure looks like this.
CREATE PROCEDURE spOrderPlaatsen
(
#tijd time(0),
#klantnr integer,
#ophaaldatum date,
#afleverdatum date,
#palletnr integer,
#aantal integer,
#Adres Varchar(255)
)
AS
BEGIN TRANSACTION
DECLARE #ordernr int
DECLARE #besteldatum date
set #besteldatum = getdate()
SELECT #ordernr = MAX(o.ordernr) + 1
FROM orders o
insert into orders values (#ordernr, #besteldatum, #tijd, #klantnr, #ophaaldatum, #afleverdatum, #adres)
insert into orderregel values (#ordernr, #palletnr, #aantal)
IF ##ERROR <> 0
BEGIN
ROLLBACK
RAISERROR ('Error tijdens het plaatsen van order.', 16, 1)
RETURN
END
COMMIT
go
Somehow we get a conversion error that we cannot find.
Could any1 figure this out for us? It would be greatly appreciated
There are multiple places where this could be going wrong. Here is some advice:
Execute the stored procedure with explicit parameters (see here for an example). Do not ever just dump the parameters into the query string.
Always list the columns for an insert. So, this should be insert into orders(col1, col2, col3, . . .) for whatever columns you are including.
Use identity so ordernr is calculated automatically by the database. You can get the value using an OUTPUT clause in the INSERT.
Similarly, you might want besteldatum to default to the current date -- or not. I'm not sure what this column really is, but a default would be appropriate for a create date column.
Surround the entire body of the stored procedure in its own BEGIN/END block (don't depend on the BEGIN TRANSACTION.
I'm having to restructure how an existing program deals with the database.
Before, I was executing statements using odbc_php consecutively.
E.g
SELECT [Value1] FROM TABLE save to $value1
INSERT INTO TABLE2 (VALUE2) VALUES ('$value1')
UPDATE TABLE SET [Value1] = '" . $value1 + 1 . "'
You get the idea.
However I believe this way of running statements is causing conflict with 'other users' of the database.
My solution is to run the statements as an implicit transaction, however I require values being saved & reused during this transaction.
so, How do I save values from select statements in MSSQL?
(My skills are not ideal for MSSQL so any good tutorial or help document are apperciated)
You have some issues with dealing with concurrent attempts to hit this sequence of commands. Given that:
You want Table2 to have an entry for every incremented value1
and
You want Table1 to have value1 incremented by 1 every time this is executed.
In which case, I think you need to update Table1 first and then insert the original value prior to the update into table2, ensuring this remains consecutive:
DECLARE #UpdatedVal TABLE (InsertVal INT)
UPDATE Table1
SET Value1 = (Value1 + 1)
OUTPUT INSERTED.Value1
INTO #InsertedVal
INSERT INTO Table2 (VALUE2)
VALUES ((SELECT(InsertVal - 1) FROM #UpdatedVal)
GO
One example:
declare #value int <\or any datatype> --create a variable
select #value = value1
from table --set the value
insert into table2 (value2) values(#value) --insert it
I am new to this forum.
I have the following environment: an Access frontend client that is connected to a database on SQL Server (backend). I would like to use an Access form to enter data that is associated with a specific ID number (in database Table). Ideally the ID will automatically increment when an INSERT is made to the Table. The vba code (based on the SQL query) I wrote is the following:
Option Compare Database
Option Explicit
Private Sub List0_Click()
Dim HelloWORLD As String
Dim dbsCurrent As Database
Set dbsCurrent = CurrentDb
CurrentDb.Execute "INSERT INTO Table1 (TESTING_1, TESTING_2) VALUES (" & 9 & "," & HelloWORLD & ")"
End Sub
The code is compiling but it is not appending the Table1 like it is supposed to do. Please Help.
You can use sequences.
You can creates sequence MySequence1 and use it:
CurrentDb.Execute "INSERT INTO Table1 (TESTING_1, TESTING_2) VALUES (NEXT VALUE FOR MyDemoSequence," & HelloWORLD & ")"
Can you make the ID field an IDENTITY field within SQL Server? This will automatically increment whenever a new row is inserted. Example from Microsoft documentation:
CREATE TABLE new_employees
(
id_num int IDENTITY(1,1),
fname varchar (20),
minit char(1),
lname varchar(30)
)
The first number is the seed, and the second is the increment, so IDENTITY(1,1) means start at '1', and increase by '1' each time.
You can retrieve the ID that was created using SELECT SCOPE_IDENTITY(); following the insert if necessary.
After create a Stored Procedure in a Table " dbo.terms" to insert a data in it using this code:
CREATE PROCEDURE dbo.terms
#Term_en NVARCHAR(50) = NULL ,
#Createdate DATETIME = NULL ,
#Writer NVARCHAR(50) = NULL ,
#Term_Subdomain NVARCHAR(50) = NULL
AS
BEGIN
SET NOCOUNT ON
INSERT INTO dbo.terms
(
Term_en ,
Createdate ,
Writer ,
Term_Subdomain
)
VALUES
(
#Term_en = 'Cat' ,
#Createdate = '2013-12-12' ,
#Writer = 'Fadi' ,
#Term_Subdomain = 'English'
)
END
GO
I want to Create a Trigger in it to add another rows in a table dbo.term_prop
I used this code :
CREATE TRIGGER triggerdata
AFTER INSERT
ON dbo.terms
FOR EACH ROW
BEGIN
INSERT INTO dbo.term_prop VALUES
('قطة', term_ar, upper(:new.term_ar) , null , 'chat', term_fr, upper(:new.term_fr) , null ,'Animal', Def_en, upper(:new.Def_en) , null ,'حيوان', Def_ar, upper(:new.Def_ar) , null ,'Animal', Def_fr, upper(:new.Def_fr) , null);
END;
and it shows me an Error
To add more rows you can use SELECTED table.
This is a special table populated with rows inserted in your transaction.
An example is:
INSERT INTO dbo.term_prop VALUES
SELECT * FROM inserted
So you mustn't use FOR EACH ROW.
The correct definition of your trigger will be
CREATE TRIGGER triggername ON table AFTER INSERT
AS BEGIN
END
Joe answer is a good one and this is more a advice.
Avoid triggers, they can cause maintenance nightmares: are trick to maintain and debug.
If you want to inserts tables in another table after inserting in the first one just put that code in the same SP.
If you need a auto identity generated value you can do it by using ##identity or scope_identity() or ident_current().
Try to keep things simple.
Wow, I am still surprised that triggers are given a bad wrap! I wrote a dozen articles on them a long time ago ...
Like anything in life, the use of triggers depends on the situation.
1 - Trigger are great to track DDL changes. Who changed that table?
http://craftydba.com/?p=2015
2 - Triggers can track DML changes (insert, update, delete). However, on large tables with large transaction numbers, they can slow down processing.
http://craftydba.com/?p=2060
However, with today's hardware, what is slow for me might not be slow for you.
3 - Triggers are great at tracking logins and/or server changes.
http://craftydba.com/?p=1909
So, lets get back to center and talk about your situation.
Why are you trying to make a duplicate entry on just an insert action?
Other options right out of the SQL Server Engine to solve this problem, are:
1 - Move data from table 1 to table 2 via a custom job. "Insert Into table 1 select * from table 2 where etl_flag = 0;". Of course make it transactional and update the flag after the insert is complete. I am just considering inserts w/o deletes or updates.
2 - If you want to track just changes, check out the change data capture. It reads from the transaction log. It is not as instant as a trigger, ie - does not fire for every record. Just runs as a SQL Agent Job in the background to load cdc.tables.
3 - Replicate the data from one server1.database1.table1 to server2.database2.table2.
ETC ...
I hope my post reminds everyone that the situation determines the solution.
Triggers are good in certain situations, otherwise, they would have been removed from the product a long time ago.
And if the situation changes, then the solution might have to change ...
I am trying to create procedure which will insert two values in my Pickup table.
create procedure sp_InsertPickup
#ClientID int,
#PickupDate date
as
insert into Pickup (ClientID ,PickupDate )values (#ClientID,#PickupDate)
However I need check if this client already did pickup in this month (record in table)it should not insert any new records it table.
example if this data in table
ClientID PickupDate
11 03-01-2013
And I want insert ClientId 11 and new PickupDate 03-24-2013 it should just not insert because this person already did pickup this month.
Any Ideas how to implement it ?
So in that case, use a IF NOT EXISTS:
CREATE PROCEDURE dbo.InsertPickup
#ClientID int,
#PickupDate date
AS
IF NOT EXISTS (SELECT * FROM Pickup
WHERE ClientID = #ClientID
AND MONTH(PickupDate) = MONTH(#PickupDate)
AND YEAR(PickupDate) = YEAR(#PickupDate) )
INSERT INTO Pickup (ClientID, PickupDate)
VALUES (#ClientID, #PickupDate)
You might want to somehow indicate to the caller that there was no data inserted, due to the fact it already exists....
As a side note: you should not use the sp_ prefix for your stored procedures. Microsoft has reserved that prefix for its own use (see Naming Stored Procedures), and you do run the risk of a name clash sometime in the future. It's also bad for your stored procedure performance. It's best to just simply avoid sp_ and use something else as a prefix - or no prefix at all!
The safest way to do this is to either use merge or to put a constraint on the table and trap for the error.
The reason merge is safer is because it is an atomic transaction. Checking for existence and then doing the insert is dangerous, because someone else might have already inserted (or deleted) the row. You can start playing with transaction semantics in the stored procedure, but why bother when SQL Server provides merge:
merge Pickup as target
using (select #PickupDate, #ClientId) as source(PickupDate, ClientId)
on target.clientId = source.ClientId and year(source.PickupDate) = year(target.PickupDate) and month(source.PickupDate) = month(target.PickupDate)
when NOT MATCHED then
insert(PickupDate, ClientId) values(source.PickupDate, source,ClientId);
You can read more about merge an.
This is how you can implement it using IF NOT EXISTS
create procedure sp_InsertPickup
#ClientID int,
#PickupDate date
as
IF NOT EXISTS (SELECT * FROM Pickup
WHERE ClientID = #ClientID
AND DATEPART(mm,PickupDate) = DATEPART(mm,#PickupDate)
AND DATEPART(yy,PickupDate) = DATEPART(yy,#PickupDate))
BEGIN
insert into Pickup (ClientID ,PickupDate )values (#ClientID,#PickupDate)
END
begin
end