I don't see where you have defined QMSTORE - I am assuming you want this as a parameter or variable. Either way - you should define that and include any wildcards.
For the mainyear parameter - set a default value to an empty string and define that as varchar(4) instead of varchar(50) - unless you can have a year designation that is 50 characters long.
With that - you can then build out your command string and pass that to sp_executeSql with parameters passed into the dynamic code. Here is an example:
Declare @mainyear varchar(4) = '2018'
, @QMSTORE varchar(50) = '%some value%';
Declare @sqlCommand nvarchar(max) = '';
Set @sqlCommand = '
Insert Into dbo.ledgertable (
transferdate
, voucherno
, itemno
, itemname
, {column name???}
, {column name???}
, quantity
, to_dept
, remarks
)
Select lt.transferdate
, lt.voucherno
, lt.itemno
, lt.itemname
, Null
, Null
, lt.quantity
, lt.to_dept
, lt.remarks
From dbo.ledgertable%%%mainyear%%% lt
Where lt.to_dept Like @qmstore;'
Set @sqlCommand = replace(@sqlCommand, '%%%mainyear%%%', @mainyear);
Print @sqlCommand;
--Execute sp_executeSql @sqlCommand, '@qmstore varchar(50)', @qmstore = @QMSTORE;
Set @sqlCommand = '
Insert Into dbo.ledgertable (
transferdate
, voucherno
, itemno
, itemname
, {column name???}
, {column name???}
, quantity
, to_dept
, remarks
)
Select lt.transferdate
, lt.voucherno
, lt.itemno
, lt.itemname
, Null
, Null
, lt.quantity
, lt.to_dept
, lt.remarks
From dbo.ledgertable%%%mainyear%%% lt
Where lt.to_dept Not Like @qmstore;'
Set @sqlCommand = replace(@sqlCommand, '%%%mainyear%%%', @mainyear);
Print @sqlCommand;
--Execute sp_executeSql @sqlCommand, '@qmstore varchar(50)', @qmstore = @QMSTORE;
Set @sqlCommand = '
Insert Into dbo.ledgertable (
transferdate
, voucherno
, itemno
, itemname
, {column name???}
, quantity
, {column name???}
, to_dept
, remarks
)
Select pt.purdt
, pt.voucherno
, pt.itemno
, pt.itemname
, pt.purqt
, Null
, Null
, Null
, pt.remarks
From dbo.purchase%%%mainyear%%% pt'
Set @sqlCommand = replace(@sqlCommand, '%%%mainyear%%%', @mainyear);
Print @sqlCommand
--Execute sp_executeSql @sqlCommand;
Once the command string is created - we then update the command string to replace the main year identifier with the appropriate value that results in the specified table to be utilized.
Note: this will fail if you pass in an invalid year - or where you pass in a year that does not have an associated table. You should put some code in place to validate the year that is passed in is valid - if not, the code will fail because the expected yearly tables do not exist.
In the insert statements - it is a very good idea to name each column that you are inserting into...this way you can insure that you are putting the quantity value into the correct column depending on which statement is being executed. And - if those columns default to null you can drop them out of the insert statement completely.
And finally - even when creating dynamic SQL it is good practice to format the code for readability. Putting everything in a single line is much harder to read and debug.