Dynamic SQL, conversion problem between varchar and money datatypes

  • create table mytable (fee1 money, fee2 money, fee3 money)

    create table mytotals (feetotal money)

    insert into mytable values (32, 11, 24)

    insert into mytable values (12, 25, 44)

    insert into mytable values (16, 14, 42)

    I need to summarize totals for each column and insert them into another table, into a field of money datatype.

    The problem is I need (or at least I think I need) to use dynamic SQL because the number of 'fee' fields could be changing over time.

    Now there are 3 fields, tomorrow there could be 4 or 5.

    My code:

    declare @i int

    declare @err int

    declare @sql varchar(200)

    set @i = 1

    set @err = 0

    while @err = 0

    begin

    set @sql = 'select sum(fee' + cast(@i as varchar) + ')

    from mytable'

    exec(@sql)

    insert mytotals values (@sql)

    end

    This code gives me an error trying to convert varchar (@sql) into money.

    Thanks in advance!

  • I am going to answer your specific question, but first I am going to try to give you some advice that I think will save you some pain down the line first. So please stick with me.

    Do you have the option of re-designing the database? The current table design violates Normal Form. You really should have a fees table that allows you to store fees as rows. I am assuming each different fee is a different type of fee. For example a school may have Lab Fees, Sports Fees, Drama Fees. In this instance I would have fees (id, description, amount), students (id, name, etc...), student_fees(id, student_id, fee_id), student_fee_receipts(student_fee_id, amount). In this design you can have N fees and the same query will work for all. For example this query will show the total fee amount owed by a student:

    [font="Courier New"]SELECT

       student_id,

       SUM(amount) AS total_owed

    FROM

       student_fees SF JOIN

       fees F ON

           SF.fee_id = F.fee_id

    GROUP BY

       SF.student_id[/font]

    And this gets by student and fee:

    [font="Courier New"]SELECT

       SF.student_id,

       SF.fee_id,

       SUM(amount) AS total_owed

    FROM

       student_fees SF JOIN

       fees F ON

           SF.fee_id = F.fee_id

    GROUP BY

       SF.student_id,

       SF.fee_id[/font]

    Anyway all that because I hate to see someone head down the path you are on IF it can be avoided. Now on to your question:

    To do what you want you would do:

    Insert Into mytotals

    Exec (@sql)

    What you are doing is trying to put the SQL String you have built into the total column of your mytotals table, not the results of the statement. You do realize that as you add fee columns you are going to have to edit your code to change the number of times you loop so get a total for each fee column, so you might as well write standard SQL using a union and just add a new query to the union when you add a new fee column.

  • Thank you!

    This helped a lot!

    Now, I have another task to do - I need to summarize values of all the 'fee' fields for each row.

    Now there three 'fee' fields, but since I don't know how many of them could be there in the future, I need to use dynamic SQL to do that.

    Can't figure out how.

  • Jack's got it right: normalize! If you can't, then you are going to have to use dynamic SQL. It's not that dynamic SQL is "bad", it has it's uses, it's just that this doesn't appear on the surface to be a good fit. Why don't you know how many "fee" columns there will be? Is this a table coming from an external source?

  • Yes, exactly so - it's a table coming from an external source.

  • So how are you accessing the external source?

    There really isn't an easy way to do it, nor is there an easy way to explain how I'd do it.

    If you have the appropriate access you could use INFORMATION_SCHEMA.COLUMNS which is an ANSI Standard view of all the columns in the database. So you'd have a query like:

    Select column_name from information_schema.columns where table_name = [table_name] and column_name like 'fee%'

    You could use a cursor and then within your cursor loop build your sql string. Like this (assumes you already have the cursor and base SQL prepared):

    While @@FETCH_STATUS = 0

    BEGIN

    Set @Select = ' Select Sum(' + @column + ') From table where criteria'

    Set @sql = @sql + ' Union ' + @Select

    Fetch Next From [cursor] Into

    @column

    END

  • Coming from an external source, I would normalize at the data import. If you use dynamic sql within the data import, you will save needing it to query your data... and allow SQL query optimizer to do it's job.

    Again, just my 2 cents.

  • Spend some time in converting the external data as pr YOUR requirement and avoid further pains.

  • If this is a one shot conversion or operation, you may want to add a computed column to the table

    alter table [yourtable] add CompCol_TheSum as (isnull(colA,0) + isnull(colB,0) + isnull(colC,0))

    Johan

    Learn to play, play to learn !

    Dont drive faster than your guardian angel can fly ...
    but keeping both feet on the ground wont get you anywhere :w00t:

    - How to post Performance Problems
    - How to post data/code to get the best help[/url]

    - How to prevent a sore throat after hours of presenting ppt

    press F1 for solution, press shift+F1 for urgent solution 😀

    Need a bit of Powershell? How about this

    Who am I ? Sometimes this is me but most of the time this is me

Viewing 9 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic. Login to reply