Export to Excel with VBScript

I’ve seen a lot of articles on the Internet explaining how to export a page to Excel using VBScript. Unfortunately, they all seem to have problems in their methodology.

Many of the articles are helpful, but they don’t seem to include all of the information you need in order to export HTML content successfully from a VBScript page into an Excel document.

I’ve finally found a method to successfully export my data to Excel, and I hope it will help some of you, too.

MySQL Developer Training – Day 4

On day 4, we continued where we had left off on day 3. We covered subqueries, views, prepared statements, importing and exporting data, stored routines and some of the basic functions that are available within stored routines. My notes from day 4 follow.

Day 4

Subqueries

Subqueries are the reason behind the name “structured query language,” as subqueries are “structured queries”.

  • A subquery is a query nested inside another query
  • Enclosed inside parentheses in order to specify that the subquery should be completed first
  • SELECT Language
    FROM CountryLanguage
    WHERE CountryCode = (
    SELECT Code
    FROM Country
    WHERE Name=’Finland’);

Why use a subquery?

Result Table Types:

  • Scalar – Single row with a single column
  • Row – Single row with one or more columns
  • Column – Single column with one or more rows
  • Table – One or more rows with one or more columns
  • Empty – No row or column data

Correlated and non-correlated

  • Correlated
    • References outer query
    • Cannot stand alone
    • Tend to be inefficient from a time standpoint, as the engine has to go back and forth between the inner and outer query
    • Tend to be more RAM efficient than JOINs, because it does not have to store a separate memory table from which to pull the final results
    • SELECT Country.Name
      (SELECT COUNT(*) FROM City
      WHERE CountryCode=Country.Code)
      AS CityCount FROM Country;
  • Non-correlated
    • Does not reference outer query
    • Can stand alone
    • Ideally, a non-correlated subequery would only be read once
    • SELECT Name FROM City WHERE CountryCode IN
      (SELECT Code FROM Country
      WHERE Continent=’Oceania’);

Subquery placement

  • If you place a subquery in the “column” portion of the query, then you can return and use only a scalar result
    • SELECT name,
      (SELECT MAX(Population) FROM City
      WHERE City.CountryCode = Country.Code)
      AS LargestCity
      FROM Country LIMIT 8;
  • Inside the FROM clause, you could return and use a table result, which can also include column, row and scalar results
    • Every column must have a name
    • Subquery can be a table query
      • Even if all values are not used
    • The following example is not something we could return with a JOIN
      • SELECT AVG(cont_sum)
        FROM (SELECT Continent, SUM(Population) AS ContinentSum
        FROM Country
        GROUP BY Continent)
        AS t;
    • Any time you have a subquery in a FROM clause, you must alias the created table, even if you don’t use that alias name anywhere else in the query
  • In the WHERE clause, when using an “equals” comparison, you can return and use scalar or row results
    • In order to use row results, you would have to use a tupple
      • (SELECT x, y FROM mytable WHERE key = 5) = (value, value)
      • (x, y) = (z, a)
        • Either or both sides of the tupple equation can be subqueries, themselves
    • Compares outer query with subquery results to see if they are the same
    • SELECT Continent, Name, Population
      FROM Country c
      WHERE Population = (SELECT MAX(Population)
      FROM Country c2
      WHERE c.Continent = c2.Continent
      AND Population > 0
      );

      • In the example above, you do not need the “> 0”, because simply stating the name of the column will evaluate as 0 or 1 (false or true)
  • In the WHERE clause, when using greater than or less than comparisons, you can only use and return a scalar result
    • SELECT
  • In the WHERE clause, when using IN, ALL, ANY, SOME, etc., you can use and return a table result (or any other type of result)
    • In order to use a table result, you would need to use a tupple
      • Using a tupple would look something like:
        WHERE CountryCode, Name, Population IN (SELECT Code, Name, Population FROM Country…)
      • A tupple will compare from left to right, matching the columns in the left list up with the columns in the results returned by the right set
    • SELECT Name, Population FROM City
      WHERE CountryCode IN(
      SELECT Code FROM Country
      WHERE Continent = ‘Europe’)
      ORDER BY Name LIMIT 10;
    • SELECT Name FROM City
      WHERE Population >
      ALL (SELECT Population FROM City
      WHERE CountryCode = ‘CHN’);

      • The example above will compare each result returned against all of the results returned in the subquery. If any of the results in the subquery do not match the criteria, the whole result will return false
      • The specific example above could have been optimized to read something like:
        • SELECT Name FROM City WHERE Population > (SELECT MAX(Population) FROM City WHERE CountryCode = ‘CHN’);
    • SELECT Name
      FROM Country
      WHERE Continent = ‘Europe’
      AND Code = ANY(SELECT CountryCode
      FROM CountryLanguage
      WHERE Language=’Spanish’)
      ORDER BY Name;
  • In the WHERE clause, when using EXISTS, you can only return an empty result set (you are simply checking to see if you get any results or not, you are not using any information from the query itself
    • In current versions of MySQL, this type of result is not optimized – MySQL will complete the subquery before returning 0 or 1 (true or false)
    • In future versions, this type of result should be optimized, so that the engine will stop the subquery as soon as a result is returned, and will then return a 1
    • SELECT Continent FROM Country WHERE EXISTS
      (SELECT * FROM City WHERE Code = CountryCode AND Population > 8000000)
      GROUP BY Continent;

      • Will return a list of each continent that contains at least one country with a population over 8000000
    • SELECT Continent FROM Country WHERE NOT EXISTS
      (SELECT * FROM City WHERE Code = CountryCode AND Population > 8000000)
      GROUP BY Continent;

      • Is not the opposite of the query above
      • Will return a list of each continent that contains at least one country with a population under 8000000

Other Subquery Uses

Using Subqueries in UPDATE and DELETE statements

You can use subqueries to locate rows on which you want to perform updates or you want to delete

  • Subqueries are not limited to SELECT statements
  • They can be used in DELETE and UPDATE statements
    • DELETE FROM City WHERE CountryCode IN (
      SELECT Code FROM Country WHERE LifeExpectancy < 70.0);
  • Generally, when dealing with DELETE and UPDATE statements, the subquery is used within the WHERE clause

Converting subqueries to JOINs

  • Joins can be more efficient than subqueries
    • Convert a subquery to a join if the subquery is running slowly
  • Subquery versus JOIN
    • Subquery:
      • SELECT Name FROM Country
        WHERE Code IN (
        SELECT CountryCode FROM CountryLanguage);
    • JOIN:
      • SELECT DISTINCT Name FROM Country
        JOIN CountryLanguage ON Code=CountryCode;

Views

  • Database object defined in terms of a SELECT statement
    • SELECT statement masquerading as a table
    • Will stay in the database until it is destroyed
  • Selected from base tables or views
  • Updatable
  • Views are nestable

CREATE VIEW statement

  • Define a view
  • General syntax:
    • http://dev.mysql.com/doc/refman/5.0/en/create-view.html
    • CREATE VIEW view_name AS select_statement
      • CREATE VIEW CityView AS SELECT ID, Name FROM City;
  • Optional parts of a CREATE VIEW statement
    • OR REPLACE
      • CREATE OR REPLACE CityView AS SELECT ID, Name FROM City;
      • Will replace an existing view of the same name if it exists, will create a new view if not
    • ALOGRITHM = { UNDEFINED | MERGE | TEMPTABLE }
      • UNDEFINED
      • MERGE
      • TEMPTABLE (TempTable)
        • Will create a temporary table if the view is too large to fit into RAM
    • DEFINER = { user | CURRENT_USER }
    • SQL SECURITY { DEFINER | INVOKER }
      • The definer, by default, is the person who created the view
    • column_list
      • By default, if the column_list is not specified, the names of the columns in the original table will be used as the column names in the view
      • You can optionally define new column names for each of those
      • CREATE VIEW v
        AS SELECT Country.Name AS CountryName, City.Name AS CityName
        FROM Country, City WHERE CountryCode=Code;
    • WITH CHECK OPTION (see insertable views below)
      • Places constraints on allowable modifications
      • Checks the WHERE conditions for updates
        • If the update or insert statement would result in something that would not be visible in the view, then the CHECK OPTION will stop the statement from being executed successfully
      • Example:
        • CREATE VIEW LargePop AS
          SELECT Name, Population FROM Country
          WHERE Population >= 100000000
          WITH CHECK OPTION;
        • SELECT * FROM LargePop;
        • UPDATE LargePop SET Population = Population + 1 WHERE Name=’Nigeria’

It is possible to update a table through a view

  • Can use UPDATE and DELETE
    • Updating and deleting information from a view will update or delete that information inside of the base table on which the view is based.
    • Information in the view does not actually exist in the view – it only exists inside the base table(s) on which the view is based
  • Must be one-to-one relationship
  • Updatability examples
    • CREATE VIEW EuropePop AS
      SELECT Name, Population FROM Country
      WHERE Continent = ‘Europe’;
    • UPDATE EuropePop SET Population = Population + 1 WHERE Name = ‘San Marino’;

Insertable Views

  • An updateable view can be insertable
    • Must meet additional requirements
    • No duplicate view column names
    • Must contain all columns from base table without default value
    • Cannot be derived columns (calculated, etc.)
  • Inserting views with AUTO_INCREMENT
    • LAST_INSERT_ID() will not work if the AUTO_INCREMENT column is not visible through the view

Checking Views

  • When you define a view, the object referenced must exist
  • A view can become invalid if a referenced object is removed
  • Using CHECK TABLE will show that the view is no longer valid

Altering Views

  • You can use ALTER VIEW to change an existing view
  • Is basically the same as CREATE OR REPLACE

INFORMATION_SCHEMA

  • Views table in database
  • SELECT * FROM INFORMATION_SCHEMA.VIEWS
    WHERE TABLE_NAME = ‘CityView’
    AND TABLE_SCHEMA = ‘world’\G

SHOW statements

  • Display Metadata
  • SHOW CREATE VIEW specifically for views
  • DESCRIBE
  • SHOW TABLE STATUS
  • SHOW TABLES
  • SHOW FULL TABLES

Prepared statements

  • Useful for running multiple similar queries
  • Can use same structure and change data values
  • Enhanced performance
    • Statement parsed only once by server
    • May require fewer conversions
    • Less traffic between server and client

Prepared statements from MySQL

  • Aids in testing and debugging
  • Session-bound
    • Prepared statements are tied to sessions and will be automatically destroyed when the session is closed
  • User defined variables pass values from one statement to another
    • Connection specific
    • Also known as @ variables
      • variables stay in RAM until the connection is closed
      • variables will not persist across connections
    • Use SET statement to define
    • Example syntax
      • SET @var_name = expr [, @var_name = expr]…
      • SET @myvar = 12, @myothervar = 5*2
    • Expression can evaluate to an integer, real, string or NULL
    • Coercibility is implicit
      • Uses the type of the string that we supply
      • If we do not supply a type, it will inherit the charset and collation of the connection
  • PREPARE my_stmt FROM
    ‘SELECT COUNT(*) FROM CountryLanguage WHERE CountryCode = ?’;
  • SET @code = ‘ESP’; EXECUTE my_stmt USING @code;
  • Using variables inside the prepared statement
    • You can have more than one question mark inside the prepared statement
    • They will be parsed in the order in which they appear within the statement
      • To supply multiple variables to be assigned to the multiple unknowns, you would separate the variable names with commas in the execute statement
  • If you want to destroy the prepared statement before closing the connection
    • DEALLOCATE PREPARE my_stmt;
    • DROP PREPARE my_stmt;
    • You do not have to use an unknown (question mark) inside a prepared statement

Preparing a statement

PREPARE namepop FROM ‘

SELECT Name, Population
FROM Country
WHERE Code = ?

‘;

  • Not all SQL statements can be prepared
  • Limited to the following
    • SELECT
    • Data modification: INSERT, REPLACE, UPDATE, DELETE
    • SET, DO and many SHOW statements
    • CREATE TABLE statements
  • As of MySQL 5.1, many more features were added

Exporting and Importing Data

Import Data using SQL

LOAD DATA INFILE

  • Imports data into a table from a file
  • Uses similar clauses and format specifiers as SELECT…INTO OUTFILE
  • MySQL assumes file is located on server host
    • In database data directory
  • Tab delimited or comma separated files
  • Characteristics to know about input file
  • CSV example:
    • LOAD DATA INFILE ‘C:/City.txt’ INTO TABLE City
      FIELDS TERMINATED BY ‘,’
      ENCLOSED BY ‘”‘
      LINES TERMINATED BY ‘\n’;
  • Specifying data file location as client host
    • LOAD DATA LOCAL INFILE ‘C:/City.txt’ INTO TABLE City;
    • You have to have the proper security permissions in order to do this
  • Skipping or transforming column values
    • LOAD DATA INFILE ‘C:/City.txt’ INTO TABLE City
      IGNORE 2 LINES;
  • Duplicate records
    • Can control duplicate records with IGNORE and REPLACE
    • Behavior differs slightly
    • IGNORE and REPLACE are mutually exclusive
      • REPLACE will delete the original record and create a new one with the new information if it finds a duplicated key
      • IGNORE will skip the new record if its key already exists in the table
  • To alter the structure of the data in order to make it fit into your table properly
    • LOAD DATA INFILE ‘C:/people.txt’ INTO TABLE People
      FIELDS TERMINATED BY ‘,’
      ENCLOSED BY ‘”‘
      LINES TERMINATED BY ‘\n’
      IGNORE 2 LINES
      (@skip, @firstname, @lastname, @date, address, email, …)

      • The items enclosed in parentheses above are in the order in which they appear within the data file that I’m loading
      • The items not preceded by @ symbols are the names of the columns in my table
      • The variable @skip in the example above is an undefined variable, which, by default, is equal to NULL
        • In this example, we are simply using that variable name to specify a column that does not need to be inserted into our table
    • SET Name = CONCAT(@lastname,’, ‘,@lastname),
      Birthdate = str_to_date(@date,’%b %e %Y’);

      • The date in the example above would have been in the format of Sep 6 2001

Export Data using SQL

SELECT with INTO OUTFILE

  • Writes result set directly into a file
  • MySQL assumes filepath to be in database data directory, unless otherwise specified
    • Path is relative to the host machine on which the SQL server is running
  • SELECT * INTO OUTFILE ‘C:/City.txt’ FROM City;
  • INTO OUTFILE Changes SELECT Operation
    • File written to server host, instead of over the network to client
    • If the file already exists, this command will generate an error rather than overwriting or appending
  • Specifiers
    • Default is tab delimited with newline terminators
    • Can change specifiers for all columns
      • FIELDS TERMINATED BY ‘string’
        • defines data values within a line
      • ENCLOSED BY ‘char’
      • ESCAPED BY ‘char’
      • LINES TERMINATED BY ‘string’
    • Terminator definitions
      • \N – NULL
      • \O – NUL (zero) byte
      • \b – backspace
    • Line terminator specifiers
      • Newline character is the default
    • CSV format text file example
      • SELECT * INTO OUTFILE ‘C:/City.csv’
        FIELDS TERMINATED BY ‘,’
        ENCLOSED BY ‘”‘
        LINES TERMINATED BY ‘\r’
        FROM City;

Export using the mysqldump database backup client

  • MySQL utility to export (dump) table contents
    • Full structure
    • Data only
    • Table structure only
    • In standard format
    • MySQL specifics for optimized speed
    • Compressed
  • Three ways to invoke mysqldump
    • mysqldump [options] db_name [tables]
    • mysqldump [options] –databases db_name1 [db_name2 db_name3…]
    • mysqldump [options] –all-databases
  • Can only be executed from the shell
  • Need to redirect the output into a file, otherwise it just prints the dump onto the screen
    • mysqldump -uroot -p<password> world >C:/world_dump.sql
  • File contains commands needed to recreate tables and data
  • Export to a specific table in a database
    • mysqldump -uroot -p<password> world CountryLanguage

Import using the mysqlimport client

  • MySQL utility to load data files into tables
  • Command line interface to LOAD DATA INFILE
  • mysqlimport options db_name input_file
  • Can only be executed from the shell
  • The table the information is being imported into must have the same name as the file you are loading from
  • Options
    • –help
    • –lines-terminated-by=string
    • –fields-terminated by=string…

Import data with the source command

  • Import table data
    • mysql -u root world < CountryLanguage.sql
    • Path is relative to the local machine
  • Loading the data
    • SOURCE C:/CountryLanguage.sql
    • Source uses a path relative to the client machine (your machine, not the server)
  • The default is to not write over existing databases, unless specified inside the script file that you’re loading

Stored Routines

What is a stored routine?

  • Set of SQL statements that can be stored in server
  • Types
    • Stored procedures
      • A procedure is invoked using a CALL statement, and can only pass back values using output variables
      • Procedures are database-specific
    • Stored functions
      • A function can be called from inside a statement and can only return a scalar value
      • Are invoked like a normal function
  • We use stored routines for the following reasons
    • Performance
    • Security
      • Minimal data access
      • Single location processing
    • Client applications
      • One application
      • One programming language
        • Instead of trying to translate your functions, etc. into each of the different languages you’re using to access the data, you can simply write it in MySQL as a stored routine
    • Function libraries
  • Stored routine issues
    • Increased server load
      • Because MySQL is doing all of the work, none of it is being passed off to other sources
    • Limited development tools
      • You can only use MySQL commands within your stored routines
    • Limited functionality and speed
      • There is no way to compile routines, etc.
    • No debugging/profiling capabilities
      • You can trace by downloading a specific version of the source and compiling it yourself, but that is not recommended

Creating Stored Routines

Create procedure

  • CREATE PROCEDURE procedure_name() procedure_statement
    • Single statement example:
    • CREATE PROCEDURE world_record_count ()
      SELECT ‘country count ‘,COUNT(*) FROM Country;

Create function

  • CREATE FUNCTION function_name() RETURNS return_type function_statement
    • Single parameter example
      • CREATE FUNCTION ThankYou(s CHAR(20)) RETURNS CHAR(50) RETURN CONCAT(‘Thank You, ‘,s,’!’);

Compound statements

  • Delimiter and BEGIN…END
    • DELIMITER // – sets the alias of the go command as “//”
      CREATE PROCEDURE world_record_count() – creates the procedure
      BEGIN – opens our list of commands
      SELECT ‘country count ‘, COUNT(*) FROM Country; – a statement that will be run
      SELECT ‘city count ‘, COUNT(*) FROM City; – another statement
      SELECT ‘countrylanguage count’, COUNT(*) FROM countrylanguage; – another statement
      END// – ends our list of commands and then tells the server to execute
      DELIMITER ; – sets the delimiter back to a semi-colon

Assign Variables

  • DECLARE
    • Declaring
    • Scope
      • Variables declared within a function definition are only valid within that function defnition
    • DELIMITER //
      CREATE FUNCTION add_tax (total_charge FLOAT(9,2)
      RETURNS FLOAT(10,2)
      BEGIN
      DECALRE tax_rate FLOAT(3,2) DEFAULT 0.07;
      RETURN total_charge + total_charge * tax_rate;
      RETURN Fbill;
      END //
      DELIMITER ;
  • SELECT … INTO
    • Global variables
      • SELECT SUM(population) FROM country INTO @worldpop;
        …is equivalent to…
        SELECT SUM(population) INTO @WorldPop FROM country;
      • SELECT SUM(population), AVG(population) FROM Country INTO @worldpop, @worldavg;
    • Local Variables
      • SELECT COUNT(*) FROM city INTO Total_Cities;
        …is equivalent to…
        SELECT COUNT(*) INTO Total_Cities FROM City;
  • SET
    • The SET statement allows the user to assign a value to a user defined variable using either = or := as the assignment operator

Variable Scope

  • Local Variable
  • Routine parameter
  • Local variable in an inner block
  • Local variable in an outer block
  • DELIMITER //
    CREATE PROCEDURE precedence(opal INT)
    BEGIN
    DECLARE opal INT DEFAULT 0;
    SELECT opal FROM test_table;
    BEGIN
    DECLARE opal INT DEFAULT 1;
    SELECT opal FROM test_table;
    END;
    END//
    DELIMITER ;
  • Variables must be defined immediately after the BEGIN statement in the block

Parameter declarations

  • Stored procedures
    • IN (Default)
      • Indicates an input parameter which is passed in from the caller to the procedure
    • OUT
      • Indicates an output parameter which is set by the procedure and passed to the caller after the procedure terminates
      • NULLs the variable when it’s passed to the function
      • Can be used to set a “success/failure” flag
    • INOUT
      • Indicates a parameter that can act as an IN and an OUT parameter
    • OUT and INOUT variables will be passed ByRef (meaning that anything that happens to the variable inside of the procedure will happen to the original variable)
  • Stored functions
    • For stored functions, only IN is available

Execute Stored Routines

  • Executing procedures
  • Executing functions
  • Implications of database association
    • You need to declare the appropriate database in which the routine is stored
    • If the database is deleted, the routine is deleted, too

Alterable stored routine characteristics

  • ALTER PROCEDURE/FUNCTION
    • SQL SECURITY
      • DEFINER
      • INVOKER
    • Data use (SQL)
      • CONTAINS SQL
      • NO SQL
      • READS SQL DATA
      • MODIFIES SQL DATA
    • COMMENT

Non-alterable stored routine characteristics

  • Non-alterable
    • DETERMINISTIC
      • The routine always produces the same result when invoked with a given set of input parameter values
    • NOT DETERMINISTIC (default)
      • The routines results can possibly change when invoked with a given set of input parameter values
    • LANGUAGE
      • Provides the parser with the programming language to use when parsing the stored routine created
      • This cannot change because MySQL is the only language available

Examine Stored Routines

  • SHOW CREATE PROCEDURE/FUNCTION
  • SHOW PROCEDURE/FUNCTION STATUS
  • INFORMATION_SCHEMA.ROUTINES

Delete Stored Routines

DROP PROCEDURE [IF EXISTS] procedure_name;
DROP FUNCTION [IF EXISTS] function_name;

Flow control statements

  • Statements and constructs that control order of operation execution
  • Common flow controls
    • Choices
      • IF
        • IF(test condition) THEN

          ELSEIF(test condition) THEN

          ELSE

          END IF;
        • ELSEIF needs to be all one word
      • CASE
        • CASE provides a means of developing complex conditional constructs
        • CASE works on the principle of comparing a given value with specified constants and acting upon the first constant that is matched
        • CASE case_value
          WHERE when_value THEN

          ELSE

          END CASE;
        • CASE
          WHEN test_condtion THEN

          ELSE

          END CASE
        • If none of the cases are met and there is no “else” specified, it will throw an error
        • In the first example, it is strictly a binary comparison, meaning that case-sensitivity is a factor
    • Loops
      • REPEAT
        • The repeat statement repeats and SQL statement until the search condition that is set becomes true
        • A repeat statement is always run at least once
        • Labels: Begin and End
        • begin_label: REPEAT

          UNTIL test_condition
          END REPEAT end_label;
      • WHILE
        • WHILE repeats an SQL statement while a set condition is true
        • The statement list can consist of one or more statements
        • begin_label: WHILE test_condition DO

          END WHILE end_label;
      • LOOP
        • The statements within the loop are repeated until the loop is exited; usually this is accomplished with a LEAVE statement
        • begin_label: LOOP

          IF…THEN
          LEAVE label;
          END IF
          END LOOP end_label;
  • Other Label Flow Control Constructs
    • LEAVE
      • This statement is used to exit any labeled flow control construct within a LOOP, REPEAT or WHILE statement
      • LEAVE can also be used in Labeled BEGIN…END compound statements
    • ITERATE
      • This statement simply means “do the LOOP (or REPEAT or WHILE) again”