Have you ever set up tables in snowflake and realized later than you have varchar types instead of currency fields? This is common in Snowflake since it’s not a relational database platform. It can be set up to function in a similar way to support various BI platforms.
I was manually adding a new column as a NUMBER(38,2)) and then copying all the data from the varchar column to that in the right format using the TRY_CAST([column name] AS NUMBER(38,2)) and then deleting the old column and renaming the new one to the old name. This was pretty time intensive and prone to user error. So, here is a better way using a stored procedure that you can list the columns you want to alter and then run the procedure to quickly change them.
Note: You can’t alter the column directly from varchar to number(38,2) in a single statement.
Why do this? In BI applications, in order to use a field for measurement, you must have numerical values and varchar fields won’t cut it.
Here is the code.
CREATE OR REPLACE PROCEDURE change_column_types()
RETURNS STRING
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
// The name of the table you want to change
var table = '[schema].[database].[table]';
// List of columns to change
var columns = ['AMOUNTDUE', 'CREDITAMT', 'INVOICED', 'PAID', 'RETAINAGE'];
columns.forEach(function(column) {
var sql;
// Add new column with NUMBER(38,2) type
sql = 'ALTER TABLE ' + table + ' ADD COLUMN ' + column + '_new NUMBER(38,2);';
snowflake.execute({sqlText: sql});
// Copy data from old column to new column with casting
sql = 'UPDATE ' + table + ' SET ' + column + '_new = TRY_CAST(' + column + ' AS NUMBER(38,2));';
snowflake.execute({sqlText: sql});
// Drop old column
sql = 'ALTER TABLE ' + table + ' DROP COLUMN ' + column + ';';
snowflake.execute({sqlText: sql});
// Rename new column to old column name
sql = 'ALTER TABLE ' + table + ' RENAME COLUMN ' + column + '_new TO ' + column + ';';
snowflake.execute({sqlText: sql});
});
return 'Column types changed successfully.';
$$;
-- To execute the procedure
CALL change_column_types();
That should do it. Just add the table name and update the array of columns you want to alter. As always, I recommend backing up the table you are altering. There is nothing worse than accidentally dropping a table with lots of data.
Happy coding.